home *** CD-ROM | disk | FTP | other *** search
/ Just Call Me Internet / Just Call Me Internet.iso / prog / atari / m2 / cat3src / cat / msglistb.i < prev    next >
Text File  |  1997-10-26  |  88KB  |  2,739 lines

  1. IMPLEMENTATION MODULE MsgListBase;
  2.  
  3.  
  4. (*==============================================================*
  5.  * Modul:               CAT-Basismodul fr Stichwortlisten      *
  6.  * Autor:               Dirk Steins                             *
  7.  * erstellt am:         27.07.1995                              *
  8.  * letzte Žnderung am:  27.07.1995                              *
  9.  * Version:             0.1                                     *
  10.  * Interne Version:     V#0001                                  *
  11.  *==============================================================*
  12.  
  13.  *----------------------------------------------------------------------------
  14.  * Datum    Vers. Autor  Žnderung (Arbeitsbericht)
  15.  *----------------------------------------------------------------------------
  16.  *----------------------------------------------------------------------------
  17.  *)
  18.  
  19. (*-- MM2-Module ------------------------------------------------------------*)
  20. FROM SYSTEM     IMPORT ADDRESS, ADR, TSIZE, CALLSYS, CADR;
  21. FROM Storage    IMPORT ALLOCATE, DEALLOCATE;
  22. IMPORT Lists;
  23. IMPORT GrafBase;
  24. IMPORT BinOps;
  25. IMPORT Strings;
  26. IMPORT StrConv;
  27. IMPORT MOSGlobals;
  28. IMPORT Keyboard;
  29. IMPORT Block;
  30. FROM Keyboard  IMPORT SpecialCode;
  31.  
  32. (*-- Cat-Module ------------------------------------------------------------*)
  33. FROM Void         IMPORT v;
  34. FROM UserInformation IMPORT UserBLK;
  35.  
  36. IMPORT data;
  37. IMPORT dataSys;
  38. IMPORT EditTypes;
  39. IMPORT MTE;
  40. IMPORT VDIStandards;
  41. IMPORT VDIUtil;
  42. IMPORT MausTauschrsc;
  43. IMPORT CatTypes;
  44. IMPORT handlePool;
  45. IMPORT ConfVars;
  46. IMPORT WdwManager;
  47. IMPORT RectFuncs;
  48. IMPORT FontSelect;
  49. IMPORT CatGlobal;
  50. IMPORT CatFiles;
  51. IMPORT grin;
  52. IMPORT grinTools;
  53. IMPORT Varnames;
  54. IMPORT QuickSort;
  55. IMPORT ZSearchDial;
  56. IMPORT GroupSelect;
  57. IMPORT Clip;
  58. IMPORT SearchHelp;
  59. IMPORT AssFuncs;
  60. IMPORT ConvertDate;
  61. IMPORT Protokoll;
  62.  
  63. (*-- Magic-Lib -------------------------------------------------------------*)
  64. IMPORT MagicStrings;
  65. IMPORT MagicAES;
  66. IMPORT MagicVDI;
  67. IMPORT MagicFSM;
  68. IMPORT MagicDOS;
  69. IMPORT MagicConvert;
  70.  
  71. (*-- Magic-Tools -----------------------------------------------------------*)
  72. IMPORT mtAppl;
  73. IMPORT mtArea;
  74. IMPORT mtUtils;
  75. IMPORT mtAlerts;
  76. IMPORT mtDials;
  77. IMPORT mtPopups;
  78. IMPORT mtTextfiles;
  79. IMPORT mtXobjects;
  80.  
  81. (* ---- msgList, zirkul„rer Import auf Implementationsbasis *)
  82.  
  83. IMPORT msgList;
  84.  
  85. (*-------------- Suchfunktionen in Liste -----------------------*)
  86.  
  87. TYPE intPtr     = POINTER TO INTEGER;
  88.      cardPtr    = POINTER TO CARDINAL;
  89.      adrPtr     = POINTER TO ADDRESS;
  90.  
  91. (*$A+,Z-*)
  92. PROCEDURE FindWinCond(e, i : ADDRESS):BOOLEAN;
  93. (* Abbruchprozedur, wie in <Lists> gefordert *)
  94. BEGIN
  95.   RETURN listWdwPtr(e)^.wdw = intPtr(i)^
  96. END FindWinCond;
  97.  
  98. PROCEDURE FindHandleCond(e, i : ADDRESS):BOOLEAN;
  99. (* Abbruchprozedur, wie in <Lists> gefordert *)
  100. BEGIN
  101.   RETURN e = adrPtr(i)^
  102. END FindHandleCond;
  103.  
  104. PROCEDURE FindGroupCond (e, i : ADDRESS): BOOLEAN;
  105. BEGIN
  106.   RETURN listWdwPtr(e)^.grHandle^.group = cardPtr(i)^
  107. END FindGroupCond;
  108. (*$A=,Z=*)
  109.  
  110. TYPE NumSet  = SET OF [0..255];
  111.  
  112. VAR listNums : NumSet;
  113.     
  114.  
  115. PROCEDURE FindNum () : INTEGER;
  116.   VAR i : INTEGER;
  117. BEGIN
  118.   IF (globalNumber >= 0) & 
  119.      ~ (globalNumber IN listNums)
  120.   THEN
  121.     INCL (listNums, globalNumber);
  122.     i := globalNumber;
  123.     globalNumber := -1;
  124.     RETURN i
  125.   END;
  126.   FOR i := 0 TO 255 DO
  127.     IF ~(i IN listNums) THEN INCL (listNums, i); RETURN i; END;
  128.   END;
  129. END FindNum;
  130.  
  131. PROCEDURE ClearNum (num : INTEGER);
  132. BEGIN
  133.   EXCL (listNums, num);
  134. END ClearNum;
  135.  
  136. (*-------------- Serviceprozeduren fr grin (next/prev) -------*)
  137. PROCEDURE findMsgIdx (ptr : listWdwPtr; which: CARDINAL; VAR idx : CARDINAL);
  138.   VAR i : CARDINAL;
  139. BEGIN
  140.   WITH ptr^ DO
  141.     IF (which <= maxPos) & 
  142.        (list^[which].msgNum = which) 
  143.     THEN 
  144.       idx := which
  145.     ELSE
  146.       FOR i := maxPos TO 0 BY -1 DO
  147.         IF list^[i].msgNum = which THEN idx := i; RETURN END
  148.       END;
  149.       idx := dataSys.empty;
  150.     END;
  151.   END;
  152. END findMsgIdx;
  153.  
  154. PROCEDURE FindNextSelected (ptr : listWdwPtr; which : CARDINAL) : CARDINAL;
  155.   VAR i, idx : CARDINAL;
  156.       bits   : BITSET;
  157. BEGIN
  158.   (* Messageindex suchen *)
  159.   findMsgIdx (ptr, which, idx);
  160.   IF idx < dataSys.notSaved
  161.   THEN
  162.     WITH ptr^ DO
  163.       FOR i := idx+1 TO maxPos DO
  164.         IF Selected IN list^[i].flags THEN 
  165.           IF unreadOrNew & UserBLK.ignoreRead & ~(initRead IN list^[i].flags)
  166.           THEN
  167.             data.ReadState (grHandle^.Zugriff, list^[i].msgNum, bits);
  168.             IF ~(dataSys.bGelesen IN bits)
  169.             THEN
  170.               RETURN list^[i].msgNum 
  171.             END;
  172.           ELSE
  173.             RETURN list^[i].msgNum 
  174.           END;
  175.         END;
  176.       END;
  177.     END;
  178.   END;
  179.   RETURN dataSys.empty
  180. END FindNextSelected;
  181.  
  182. PROCEDURE FindPrevSelected (ptr : listWdwPtr; which : CARDINAL) : CARDINAL;
  183.   VAR i, idx : CARDINAL;
  184.       bits   : BITSET;
  185. BEGIN
  186.   (* Messageindex suchen *)
  187.   findMsgIdx (ptr, which, idx);
  188.   IF idx < dataSys.notSaved
  189.   THEN
  190.     WITH ptr^ DO
  191.       IF idx > 0
  192.       THEN
  193.         FOR i := idx-1 TO 0 BY -1 DO
  194.           IF Selected IN list^[i].flags THEN 
  195.             IF unreadOrNew & UserBLK.ignoreRead & ~(initRead IN list^[i].flags)
  196.             THEN
  197.               data.ReadState (grHandle^.Zugriff, list^[i].msgNum, bits);
  198.               IF ~(dataSys.bGelesen IN bits)
  199.               THEN
  200.                 RETURN list^[i].msgNum 
  201.               END;
  202.             ELSE
  203.               RETURN list^[i].msgNum 
  204.             END;
  205.           END;
  206.         END;
  207.       END;
  208.     END;
  209.   END;
  210.   RETURN dataSys.empty
  211. END FindPrevSelected;
  212.  
  213. (* Deselektierte suchen, fr Bestimmung von neuer Startpoistion *)
  214. PROCEDURE FindNextDeselected (ptr : listWdwPtr; which : CARDINAL) : CARDINAL;
  215.   VAR i, idx : CARDINAL;
  216. BEGIN
  217.   (* Messageindex suchen *)
  218.   findMsgIdx (ptr, which, idx);
  219.   IF idx < dataSys.notSaved
  220.   THEN
  221.     WITH ptr^ DO
  222.       FOR i := idx+1 TO maxPos DO
  223.         IF ~(Selected IN list^[i].flags) THEN RETURN list^[i].msgNum END;
  224.       END;
  225.     END;
  226.   END;
  227.   RETURN ptr^.maxPos+1
  228. END FindNextDeselected;
  229.  
  230. PROCEDURE FindPrevDeselected (ptr : listWdwPtr; which : CARDINAL) : CARDINAL;
  231.   VAR i, idx : CARDINAL;
  232. BEGIN
  233.   (* Messageindex suchen *)
  234.   findMsgIdx (ptr, which, idx);
  235.   IF idx < dataSys.notSaved
  236.   THEN
  237.     WITH ptr^ DO
  238.       IF idx > 0
  239.       THEN
  240.         FOR i := idx-1 TO 0 BY -1 DO
  241.           IF ~(Selected IN list^[i].flags) THEN RETURN list^[i].msgNum END;
  242.         END;
  243.       END;
  244.     END;
  245.   END;
  246.   RETURN dataSys.empty;
  247. END FindPrevDeselected;
  248.  
  249. PROCEDURE listNextMess (which : CARDINAL; nextJN, withShift: BOOLEAN; listHdl: LONGCARD; wdw : ADDRESS):CARDINAL;
  250.   VAR ptr : listWdwPtr;
  251. BEGIN
  252.   IF handlePool.FindEntry(ADR(listHdl), FindHandleCond, windows, ptr) THEN
  253.     IF nextJN
  254.     THEN
  255.       RETURN FindNextSelected (ptr, which)
  256.     ELSE
  257.       RETURN FindPrevSelected (ptr, which)
  258.     END;
  259.   ELSE
  260.     RETURN grin.grinNextMess (which, nextJN, withShift, 0, NIL);
  261.   END;
  262. END listNextMess;
  263.  
  264. PROCEDURE hasSelectedEntries (ptr : listWdwPtr; VAR first : CARDINAL): BOOLEAN;
  265.   VAR i : CARDINAL;
  266. BEGIN
  267.   WITH ptr^ DO
  268.     FOR i := 0 TO maxPos DO
  269.       IF Selected IN list^[i].flags THEN first := i; RETURN TRUE
  270.       END;
  271.     END;
  272.   END;
  273.   RETURN FALSE;
  274. END hasSelectedEntries;
  275.  
  276. PROCEDURE countSelectedEntries (ptr : listWdwPtr) : CARDINAL;
  277.   VAR i : CARDINAL;
  278.       (*$Reg *) counter : CARDINAL;
  279. BEGIN
  280.   WITH ptr^ DO
  281.     counter := 0;
  282.     FOR i := 0 TO maxPos DO
  283.       IF Selected IN list^[i].flags THEN INC (counter)
  284.       END;
  285.     END;
  286.   END;
  287.   RETURN counter;
  288. END countSelectedEntries;
  289.  
  290. (*-------------- Selektion von Eintr„gen ----------------------*)
  291. PROCEDURE toggleBit (VAR s : BITSET; bit: INTEGER);
  292. BEGIN
  293.   IF bit IN s
  294.   THEN EXCL (s, bit)
  295.   ELSE INCL (s, bit);
  296.   END;
  297. END toggleBit;
  298.  
  299. PROCEDURE redrawEntry (ptr : listWdwPtr; entry: CARDINAL);
  300.   VAR rect : GrafBase.Rectangle;
  301. BEGIN
  302.   WITH ptr^ DO
  303.     IF entry > maxPos THEN RETURN END;
  304.     rect := listWork;
  305.     INC (rect.x, pixOffset);
  306.     rect.y := rect.y + INTEGER(entry - startPos) * (charHeight+lineDist);
  307.     rect.h := charHeight + lineDist;
  308.     WdwManager.RedrawWdw (wdw, rect);
  309.     EXCL (list^[entry].flags, doRedraw);
  310.     WdwManager.SetClip (vdi, listWork, TRUE);
  311.   END;
  312. END redrawEntry;
  313.  
  314. PROCEDURE toggleEntry (ptr : listWdwPtr; entry: CARDINAL);
  315. BEGIN
  316.   WITH ptr^ DO
  317.     IF entry > maxPos THEN RETURN END;
  318.     toggleBit (list^[entry].flags, Selected);
  319.     redrawEntry (ptr, entry);
  320.   END;
  321. END toggleEntry;
  322.  
  323. PROCEDURE invertSelection (ptr: listWdwPtr);
  324.   VAR i         : CARDINAL;
  325. BEGIN
  326.   WITH ptr^ DO
  327.     FOR i := 0 TO maxPos DO
  328.       toggleBit (list^[i].flags, Selected);
  329.     END;
  330.     (* kompletten Redraw ausl”sen *)
  331.     WdwManager.FullRedrawWdw (ptr^.wdw);
  332.   END;
  333. END invertSelection;
  334.  
  335. PROCEDURE deselectEntries (ptr : listWdwPtr);
  336.   VAR i         : CARDINAL;
  337.       rect      : GrafBase.Rectangle;
  338.       first     : BOOLEAN;
  339. BEGIN
  340.   WITH ptr^ DO
  341.     rect := listWork;
  342.     INC (rect.x, pixOffset);
  343.     rect.h := charHeight + lineDist;
  344.     first := TRUE;
  345.     FOR i := 0 TO maxPos DO
  346.       IF Selected IN list^[i].flags
  347.       THEN
  348.         EXCL (list^[i].flags, Selected);
  349.         IF (i >= startPos) & (i <= startPos + CARDINAL(windLines))
  350.         THEN 
  351.           (* redraw *)
  352.           IF first THEN 
  353.             rect.y := listWork.y + INTEGER(i - startPos) * (charHeight+lineDist);
  354.             first := FALSE
  355.           ELSE
  356.             rect.h := listWork.y + INTEGER(i - startPos + 1) * (charHeight+lineDist) - rect.y;
  357.           END;
  358.         END;
  359.       END;
  360.     END;
  361.     IF ~first THEN WdwManager.RedrawWdw (wdw, rect) END;
  362.   END;
  363. END deselectEntries;
  364.  
  365. PROCEDURE deselectReadEntries (ptr : listWdwPtr);
  366.   VAR i         : CARDINAL;
  367.       rect      : GrafBase.Rectangle;
  368.       first     : BOOLEAN;
  369.       bits      : BITSET;
  370. BEGIN
  371.   WITH ptr^ DO
  372.     rect := listWork;
  373.     INC (rect.x, pixOffset);
  374.     rect.h := charHeight + lineDist;
  375.     first := TRUE;
  376.     FOR i := 0 TO maxPos DO
  377.       IF ~(firstRead IN list^[i].flags)
  378.       THEN
  379.         (* Wurde noch gar nicht gelesen, mal schnell den Readstatus 
  380.          * dazu rausfinden
  381.          *)
  382.         data.ReadState (grHandle^.Zugriff, list^[i].msgNum, bits);
  383.         IF dataSys.bGelesen IN bits
  384.         THEN
  385.           EXCL (list^[i].flags, notRead);
  386.         ELSE
  387.           INCL (list^[i].flags, notRead);
  388.         END;
  389.       END;
  390.       IF (Selected IN list^[i].flags) & ~(notRead IN list^[i].flags)
  391.       THEN
  392.         EXCL (list^[i].flags, Selected);
  393.         IF (i >= startPos) & (i <= startPos + CARDINAL(windLines))
  394.         THEN 
  395.           (* redraw *)
  396.           IF first THEN 
  397.             rect.y := listWork.y + INTEGER(i - startPos) * (charHeight+lineDist);
  398.             first := FALSE
  399.           ELSE
  400.             rect.h := listWork.y + INTEGER(i - startPos + 1) * (charHeight+lineDist) - rect.y;
  401.           END;
  402.         END;
  403.       END;
  404.     END;
  405.     IF ~first THEN WdwManager.RedrawWdw (wdw, rect) END;
  406.   END;
  407. END deselectReadEntries;
  408.  
  409. (* --------------------- Cursorbehandlung ------------------*) 
  410.  
  411. PROCEDURE drawCursor (ptr: listWdwPtr);
  412.   VAR line : ARRAY [0..4] OF GrafBase.Point;
  413.       fill : GrafBase.Rectangle;
  414.       xOutput, yOutput : INTEGER;
  415.       style : CARDINAL;
  416. BEGIN
  417.   WITH ptr^ DO
  418.     (* Zeichnet einen gepunkteten Rahmen um die Zeile mit der aktuellen
  419.      * Cursorposition
  420.      *)
  421.     IF (cursPos >= LONGINT(LONG(startPos))) & (cursPos <= LONGINT (LONG(startPos + CARDINAL(windLines) - 1)))
  422.     THEN
  423.       (* Cursor ist sichtbar, also zeichnen *)
  424.       xOutput := listWork.x + pixOffset - leftOffset;
  425.       yOutput := listWork.y + SHORT (cursPos - LONGINT(LONG(startPos))) * (charHeight + lineDist) + (lineDist DIV 2);
  426.       line[0].x := xOutput;
  427.       line[0].y := yOutput;
  428.       line[1].x := xOutput+entryWidth-1;
  429.       line[1].y := yOutput;
  430.       line[2].x := xOutput+entryWidth-1;
  431.       line[2].y := yOutput+charHeight-1;
  432.       line[3].x := xOutput;
  433.       line[3].y := yOutput+charHeight-1;
  434.       line[4].x := xOutput;
  435.       line[4].y := yOutput;
  436.       (* Schreibmodus setzen *)
  437.       v.int := MagicVDI.SetWritemode (vdi, MagicVDI.XOR);
  438.       (* Linientyp setzen *)
  439.       v.int := MagicVDI.SetLinetype (vdi, MagicVDI.User);
  440.       IF ODD (leftOffset)
  441.       THEN
  442.         style := $AAAA;
  443.       ELSE
  444.         style := $5555;
  445.       END;
  446.       MagicVDI.SetUserlinestyle (vdi, style);
  447.       v.int := MagicVDI.SetLinewidth (vdi, 1);
  448.       v.int := MagicVDI.SetLinecolor (vdi, 1);
  449.       MagicVDI.Polyline (vdi, 5, line);
  450.       (* Jetzt PixOffset am linken Rand ggf. l”schen *)
  451.       v.int := MagicVDI.SetWritemode (vdi, MagicVDI.REPLACE);
  452.       v.int := MagicVDI.SetFillcolor (vdi, CatGlobal.listBackCol);  (* Weiž *)
  453.       fill.x := listWork.x;
  454.       fill.y := yOutput;
  455.       fill.w := listWork.x + pixOffset - 1;
  456.       fill.h := yOutput + charHeight - 1;
  457.       MagicVDI.FillRectangle(vdi, fill);
  458.       (* Schreibmodus zurcksetzen *)
  459.       v.int := MagicVDI.SetWritemode (vdi, MagicVDI.TRANSPARENT);
  460.     END;
  461.   END;
  462. END drawCursor;
  463.  
  464. PROCEDURE ShowCursor (ptr : listWdwPtr);
  465.   VAR r : GrafBase.Rectangle;
  466. BEGIN
  467.   WITH ptr^ DO 
  468.     IF (cursPos >= LONGINT(LONG(startPos))) & (cursPos <= LONGINT (LONG(startPos + CARDINAL(windLines) - 1)))
  469.     THEN
  470.       (* Cursor ist sichtbar, also zeichnen *)
  471.       (* WindUpdate und Maus ausschalten *)
  472.       updateListWdw (wdw, vdi, ADR(ptr), TRUE);
  473.       IF WdwManager.RectList (wdw, 0, r)
  474.       THEN
  475.         REPEAT
  476.           (* ClipRechteck setzen *)
  477.           WdwManager.SetClip (vdi, r, TRUE);
  478.           (* Zeichnen *)
  479.           drawCursor (ptr);
  480.         UNTIL ~WdwManager.RectList (wdw, 1, r);
  481.       END;
  482.       (* WindUpdate wieder aus und Maus anschalten *)
  483.       updateListWdw (wdw, vdi, ADR(ptr), FALSE);
  484.     END;
  485.   END;
  486. END ShowCursor;
  487.  
  488. (*-------------- Funktionen fr WdwManager --------------------*)
  489.  
  490. PROCEDURE AdjustTreePos (r: GrafBase.Rectangle; VAR rt : GrafBase.Rectangle);
  491. BEGIN
  492.   WITH butBox^[0] DO
  493.     obX := r.x;
  494.     obY := r.y;
  495.     obWidth := r.w;
  496.     rt.x := obX; rt.y := obY;
  497.     rt.w := obWidth; rt.h := obHeight+1;
  498.   END;
  499.   (* Jetzt Userdef prfen *)
  500.   IF butBox^[MausTauschrsc.listread].obType # MagicAES.GPROGDEF
  501.   THEN
  502.     v.bool := mtXobjects.InstUserdef (butBox, MausTauschrsc.listread, mtDials.DrawButton, NIL);
  503.   END;
  504. END AdjustTreePos;
  505.  
  506. PROCEDURE GetLinePart (ptr: listWdwPtr; num : CARDINAL; VAR mess : data.MessageType; 
  507.                        VAR line : ARRAY OF CHAR; type : partType);
  508.   VAR tmpStr : ARRAY [0..1023] OF CHAR;
  509.       maxLen : CARDINAL;
  510.       i      : CARDINAL;
  511.       p, n   : INTEGER;
  512.       ch     : CHAR;
  513.       fStr   : partFormat;
  514.       dt     : ConvertDate.Date;
  515.       ti     : ConvertDate.Time;
  516.  
  517.   PROCEDURE CheckAssign (strPtr: CatTypes.Str255Ptr; VAR str : ARRAY OF CHAR);
  518.   BEGIN
  519.     IF strPtr # NIL
  520.     THEN
  521.       Strings.Assign (strPtr^, str, v.bool);
  522.     ELSE
  523.       Strings.Assign ("(not available)", str, v.bool);
  524.     END;
  525.   END CheckAssign;
  526.   
  527. BEGIN
  528.   IF (type.type = pRealName) & 
  529.      ((mess.name^[0] = '') OR mess.EigeneNachricht)
  530.   THEN
  531.     type.type := pUserName;
  532.   END;
  533.   CASE type.type OF
  534.     pRealName,
  535.     pUserName  : IF mess.EigeneNachricht & (mess.Gruppe = dataSys.private)
  536.                  THEN
  537.                    Strings.Copy ('An: ', 0, BinOps.LowerInt (type.w, 4), line, v.bool);
  538.                    CheckAssign (mess.Empfaenger, tmpStr);
  539.                    maxLen := BinOps.HigherInt (0, type.w - 4);
  540.                  ELSE
  541.                    IF type.type = pRealName  
  542.                    THEN 
  543.                      CheckAssign (mess.name, tmpStr);
  544.                    ELSE
  545.                      CheckAssign (mess.Absender, tmpStr);
  546.                    END;
  547.                    line[0]:= '';
  548.                    maxLen := type.w;
  549.                  END;
  550.                  CatGlobal.KurzName (tmpStr, tmpStr, maxLen);
  551.                  (*
  552.                  IF LENGTH (tmpStr) > maxLen
  553.                  THEN
  554.                    (* Erstmal Vornamen abkrzen *)
  555.                    p := 0;
  556.                    p := Strings.Pos (' ', tmpStr, 0);
  557.                    IF p > 0
  558.                    THEN
  559.                      n := Strings.Pos ('@', tmpStr, 0);
  560.                      IF (n-2 < p) & (n > 0)
  561.                      THEN
  562.                        (* Hinter dem @ abschneiden, da kein richtiger Vorname *)
  563.                        tmpStr [n] := 0C;
  564.                      ELSE
  565.                        (* Vornamen verkrzen *)
  566.                        Strings.Delete (tmpStr, 1, p-1, v.bool);
  567.                        Strings.Insert ('.', 1, tmpStr, v.bool);
  568.                      END;
  569.                    END;
  570.                  END;
  571.                  IF LENGTH (tmpStr) > maxLen 
  572.                  THEN 
  573.                    (* Immer noch zu lang, hinten ... anh„ngen *)
  574.                    FOR i := 1 TO 3 DO 
  575.                      tmpStr[maxLen-i] := '.';
  576.                    END;
  577.                    tmpStr[maxLen] := 0C;
  578.                  END;
  579.                  *)
  580.                  Strings.Append (tmpStr, line, v.bool);
  581.                  |
  582. (*
  583.       pRealName  : CheckAssign (mess.name, tmpStr);
  584.                  Strings.Copy (tmpStr, 0, type.w, line, v.bool); |
  585. *)
  586.     pMailId    : CheckAssign (mess.MailID, tmpStr);
  587.                  Strings.Copy (tmpStr, 0, type.w, line, v.bool); |
  588.     pMId       : CheckAssign (mess.mid, tmpStr);
  589.                  Strings.Copy (tmpStr, 0, type.w, line, v.bool); |
  590.     pRefId     : Strings.Copy (mess.KommentierteID, 0, type.w, line, v.bool); 
  591.                  IF line[0] # '' THEN Strings.Insert ('-', 0, line, v.bool); END; |
  592.     pWegen     : CheckAssign (mess.Betreff, tmpStr);
  593.                  IF LENGTH (tmpStr) > CARDINAL(type.w)
  594.                  THEN
  595.                    (* Zu lang, hinten ... anh„ngen *)
  596.                    FOR i := 1 TO 3 DO 
  597.                      tmpStr[type.w-INTEGER(i)] := '.';
  598.                    END;
  599.                    tmpStr[type.w] := 0C;
  600.                  END;
  601.                  Strings.Assign (tmpStr, line, v.bool); |
  602.     pStatus    : IF ptr^.grHandle^.group = dataSys.private
  603.                  THEN 
  604.                    line[0] := mess.Status;
  605.                  ELSE
  606.                    IF dataSys.bGelesen IN mess.StatusBits
  607.                    THEN
  608.                      line[0] := 'G';
  609.                    ELSE
  610.                      line[0] := 'N';
  611.                    END;
  612.                  END;
  613.                  line[1] := 0C; |
  614.     pDatum     : ConvertDate.CatDate2Datim (mess.tauschDate, dt, ti);
  615.                  ConvertDate.DateToText (dt, type.formatStr, line); |
  616.     pTime      : ConvertDate.CatDate2Datim (mess.tauschDate, dt, ti);
  617.                  ConvertDate.TimeToText (ti, type.formatStr, line); |
  618.     pWeekday   : ConvertDate.CatDate2Datim (mess.tauschDate, dt, ti);
  619.                  ConvertDate.DayToText (dt, type.formatStr, line); |
  620.     pFuzzytime : ConvertDate.CatDate2Datim (mess.tauschDate, dt, ti);
  621.                  ConvertDate.FuzzyTime (ti, type.formatStr, line); |
  622.     pComments  : Strings.Assign (StrConv.CardToStr (mess.KommentarAnzahl, type.w), line, v.bool); |
  623.     pCount     : Strings.Assign (StrConv.CardToStr (num+1, 0), line, v.bool); 
  624.                  Strings.Insert ('#',0, line, v.bool); |
  625.     pOwnMess   : IF (dataSys.bOwnMessage IN mess.StatusBits)
  626.                  OR (dataSys.bComToOwnMessage IN mess.StatusBits)
  627.                  THEN
  628.                    ch := '*'
  629.                  ELSE
  630.                    ch := ' ';
  631.                  END;
  632.                  FOR i := 0 TO CARDINAL(type.w) - 1 DO 
  633.                    line[i] := ch;
  634.                  END;
  635.                  line[type.w] := ''; |
  636.     pLength    : Strings.Assign (StrConv.CardToStr (mess.textLen, 5), line, v.bool);
  637.                  Strings.Append (' Bytes', line, v.bool); |
  638.     pFlags     : Strings.Assign ('-------------', line, v.bool);
  639.                  IF 0 IN mess.StatusBits THEN line[0] := 'L' END;
  640.                  IF 1 IN mess.StatusBits THEN line[1] := 'F' END;
  641.                  IF 2 IN mess.StatusBits THEN line[2] := 'I' END;
  642.                  IF 3 IN mess.StatusBits THEN line[3] := 'T' END;
  643.                  IF 4 IN mess.StatusBits THEN line[4] := 'D' END;
  644.                  IF 5 IN mess.StatusBits THEN line[5] := 'K' END;
  645.                  IF 6 IN mess.StatusBits THEN line[6] := 'B' END;
  646.                  IF 7 IN mess.StatusBits THEN line[7] := '1' END;
  647.                  IF 8 IN mess.StatusBits THEN line[8] := '2' END; 
  648.                  IF 9 IN mess.StatusBits THEN line[9] := 'V' END; 
  649.                  IF 13 IN mess.StatusBits THEN line[10] := 'C' END; 
  650.                  IF 14 IN mess.StatusBits THEN line[11] := 'E' END; 
  651.                  IF 15 IN mess.StatusBits THEN line[12] := 'X' END; |
  652.                  
  653.   ELSE
  654.   END;
  655.   Strings.Copy (line, 0, type.w, line, v.bool);
  656. END GetLinePart;
  657.   
  658. PROCEDURE rawRedraw (ptr : listWdwPtr; clip : GrafBase.Rectangle);
  659.   (* Geht davon aus, daž RectFuncs.ClipRect gesetzt ist und nur Zeilen zu zeichnen sind! 
  660.    *)
  661. VAR 
  662.     extend : ARRAY [0..3] OF GrafBase.Point;
  663.     i      : INTEGER;
  664.     width  : INTEGER;
  665.     xOutput, 
  666.     yOutput: INTEGER;
  667.     xOffset: INTEGER;
  668.     j      : INTEGER;
  669.     topLine: CARDINAL;
  670.     line   : ARRAY [0..1023] OF CHAR;
  671.     entry  : listEntry;
  672.     mess   : data.MessageType;
  673.     myClip : GrafBase.Rectangle;
  674.     fill   : GrafBase.Rectangle;
  675.     attrSet: BOOLEAN;
  676.     isOwn  : BOOLEAN;
  677. BEGIN
  678.   WITH ptr^ DO
  679.     topLine := startPos;
  680.     attrSet := FALSE;
  681.     i := 0;   (* Zeilenz„hler im Fenster *)
  682.     (* Nicht im Redrawbereich liegende Zeilen berspringen *)
  683.     WHILE (topLine <= maxPos) & ((listWork.y + (i+1)*(charHeight+lineDist)) - 1 < clip.y) DO
  684.       INC (topLine);
  685.       INC(i);
  686.     END;
  687.     xOutput := listWork.x + pixOffset - leftOffset;
  688.     yOutput := listWork.y + i * (charHeight + lineDist) + (lineDist DIV 2);
  689.     (* Eintrag in Liste suchen *)
  690.     (* Jetzt zeichnen *)
  691.     myClip := clip;
  692.     v.int := MagicVDI.SetFillcolor (vdi, MagicAES.BLACK);
  693.     v.int := MagicVDI.SetTextcolor (vdi, CatGlobal.listTextCol);
  694.     v.int := MagicVDI.SetWritemode (vdi, MagicVDI.TRANSPARENT);
  695.     WHILE (topLine <= maxPos) & (i <= listWork.h DIV (charHeight+lineDist)) 
  696.           & (yOutput <= clip.h) DO
  697.       entry := list^[topLine];
  698.       (* Header der Message lesen *)
  699.       data.ReadHeader (grHandle^.Zugriff, entry.msgNum, mess);
  700.       IF data.error # data.noError
  701.       THEN
  702.         WITH mess DO
  703.           MailID := NIL;
  704.           Betreff := NIL;
  705.           Absender := NIL;
  706.           Empfaenger := NIL;
  707.           mid := NIL;
  708.           rid := NIL;
  709.           box := NIL;
  710.           name := NIL;
  711.           InfoStrings := NIL;
  712.         END;
  713.       END;
  714.       (* Erstmal Flag in Liste updaten *)
  715.       IF dataSys.bGelesen IN mess.StatusBits
  716.       THEN
  717.         EXCL (list^[topLine].flags, notRead);
  718.       ELSE
  719.         INCL (list^[topLine].flags, notRead);
  720.       END;
  721.       (* Testen, ob Gelesen-Flag ver„ndert wurde *)
  722.       IF ((dataSys.bGelesen IN mess.StatusBits) # ~(notRead IN entry.flags))
  723.        & (firstRead IN entry.flags)
  724.       THEN
  725.         (* Eintrag muž komplett neu gezeichnet werden *)
  726.         INCL (list^[topLine].flags, doRedraw);
  727.       END;
  728.       INCL (list^[topLine].flags, firstRead);
  729.       (* Jetzt die einzelnen Zeilenteile ausgeben *)
  730.       (* Nicht gelesene werden fett dargestellt *)
  731.       isOwn := (dataSys.bComToOwnMessage IN mess.StatusBits) OR
  732.                (dataSys.bOwnMessage IN mess.StatusBits) OR
  733.                ((grHandle^.group = dataSys.private) & mess.EigeneNachricht);
  734.       IF ~(dataSys.bGelesen IN mess.StatusBits) (* & ~attrSet *)
  735.       THEN
  736.         IF mtAppl.Bitplanes = 1 THEN
  737.           IF isOwn
  738.           THEN
  739.             v.bset := MagicVDI.SetTexteffect (vdi, quoteEff+ownEff);
  740.           ELSE
  741.             v.bset := MagicVDI.SetTexteffect (vdi, quoteEff);
  742.           END;
  743.         ELSE
  744.           IF isOwn 
  745.           THEN
  746.             v.int := MagicVDI.SetTextcolor (vdi, CatGlobal.listOwnCol);
  747.           ELSE
  748.             v.int := MagicVDI.SetTextcolor (vdi, CatGlobal.listUnreadCol);
  749.           END;
  750.         END;
  751.         attrSet := TRUE;
  752.       ELSIF (dataSys.bGelesen IN mess.StatusBits) (* & attrSet *) 
  753.       THEN
  754.         IF isOwn
  755.         THEN
  756.           IF mtAppl.Bitplanes = 1
  757.           THEN
  758.             v.bset := MagicVDI.SetTexteffect (vdi, ownEff);
  759.           ELSE
  760.             v.int := MagicVDI.SetTextcolor (vdi, CatGlobal.listOwnCol);
  761.           END;
  762.         ELSE
  763.           v.bset := MagicVDI.SetTexteffect (vdi, {});
  764.           v.int := MagicVDI.SetTextcolor (vdi, CatGlobal.listTextCol);
  765.         END;
  766.         attrSet := FALSE;
  767.       END;
  768.       xOffset := 0;
  769.       FOR j := 0 TO partArray.lines-1 DO
  770.         GetLinePart (ptr, entry.msgNum, mess, line, partArray.parts[j]);
  771.         width := partArray.parts[j].w * charWidth;
  772.         myClip.w := BinOps.LowerInt (clip.w, xOutput + xOffset + width);
  773.         IF (myClip.w >= clip.x) & (xOutput+xOffset <= myClip.w)
  774.         THEN 
  775.           (* WdwManager.SetClip (vdi, myClip, FALSE); *)
  776.           VDIStandards.Text (isFSM, vdi, xOutput+xOffset, yOutput+charHeight-1, line);
  777.         END;
  778.         INC (xOffset, width + charWidth);
  779.       END;
  780.       IF Selected IN entry.flags 
  781.       THEN
  782.         (*
  783.         WdwManager.SetClip (vdi, clip, FALSE);
  784.         *)
  785.         fill.x := xOutput;
  786.         fill.y := yOutput;
  787.         fill.w := xOutput + xOffset - 1;
  788.         fill.h := yOutput + charHeight - 1;
  789.         (* Schreibmodus setzen *)
  790.         v.int := MagicVDI.SetWritemode (vdi, MagicVDI.XOR);
  791.         MagicVDI.FillRectangle(vdi, fill);
  792.         v.int := MagicVDI.SetWritemode (vdi, MagicVDI.TRANSPARENT);
  793. (*        v.int := MagicVDI.SetWritemode (vdi, MagicVDI.REPLACE); *)
  794.       END;
  795.       entryWidth := xOffset;
  796.       maxWidth := BinOps.HigherInt (maxWidth, xOffset+pixOffset);
  797.       IF mess.InfoStrings # NIL THEN 
  798.         DEALLOCATE (mess.InfoStrings, 0);
  799.       END;
  800.       IF (cursPos >= 0) & (LONGINT(LONG(topLine)) = cursPos)
  801.       THEN
  802.         drawCursor (ptr);
  803.         v.int := MagicVDI.SetFillcolor (vdi, MagicAES.BLACK);
  804.       END;
  805.       INC(i);
  806.       INC (topLine);
  807.       INC (yOutput, charHeight+lineDist);
  808.     END;
  809.     v.int := MagicVDI.SetFillcolor (vdi, CatGlobal.listBackCol);
  810.     IF attrSet THEN
  811.       IF mtAppl.Bitplanes = 1 THEN
  812.         v.bset := MagicVDI.SetTexteffect (vdi, {});
  813.       ELSE
  814.         v.int := MagicVDI.SetTextcolor (vdi, CatGlobal.listTextCol);
  815.       END;
  816.     END;
  817.   END (* WITH ptr *);
  818. END rawRedraw;
  819.  
  820.  
  821. PROCEDURE shrinkToEnd (ptr: listWdwPtr; doRedraw: BOOLEAN);
  822.   VAR i, j     : CARDINAL;
  823.       allocNew : BOOLEAN;
  824.       oldList  : listArrayPtr;
  825.       start    : CARDINAL;
  826. BEGIN
  827.   WITH ptr^ DO
  828.     IF startPos = 0 THEN RETURN END;
  829.     IF startPos > maxPos THEN HALT END;
  830.     IF wholeList = list
  831.     THEN
  832.       list := NIL;
  833.       ALLOCATE (list, LONG(maxPos - startPos + 1) * TSIZE (listEntry));
  834.       IF list = NIL
  835.       THEN 
  836.         MTE.noMemAlert();
  837.         RETURN
  838.       END;
  839.       allocNew := TRUE;
  840.       oldList := wholeList;
  841.     ELSE
  842.       oldList := list;
  843.       allocNew := FALSE;
  844.     END;
  845.     (* Erstmal neue Startposition festlegen *)
  846.     start := oldList^[startPos].msgNum;
  847.     (* Und jetzt die Liste verkleinern *)
  848.     j := 0;
  849.     FOR i := startPos TO maxPos DO 
  850.       list^[j] := oldList^[i]; 
  851.       INC (j);
  852.     END;
  853.     IF ~allocNew 
  854.     THEN
  855.       (* Speicherbereich verkleinern *)
  856.       DEALLOCATE (list, LONG (startPos) * TSIZE (listEntry));
  857.     END;
  858.     (* neue maxPos festlegen *)
  859.     maxPos := maxPos - startPos;
  860.     findMsgIdx (ptr, start, startPos);
  861.     startPos := BinOps.LowerCard (startPos, maxPos);
  862.     cursPos := -1;
  863.     IF doRedraw
  864.     THEN
  865.       (* Neues Document setzen *)
  866.       WdwManager.SetNewDocument (wdw, GrafBase.LongRect{LONG(leftOffset), startPos, LONG(maxWidth), maxPos}, FALSE);
  867.       WdwManager.FullRedrawWdw (wdw);
  868.     END;
  869.   END;
  870. END shrinkToEnd;
  871.  
  872. PROCEDURE shrinkList (ptr: listWdwPtr; removeSel : BOOLEAN; doRedraw: BOOLEAN): BOOLEAN; 
  873. (* removes the selected messages from the list *)
  874.   VAR firstSel : CARDINAL;
  875.       count    : CARDINAL;
  876.       i, j     : CARDINAL;
  877.       allocNew : BOOLEAN;
  878.       oldList  : listArrayPtr;
  879.       start    : CARDINAL;
  880. BEGIN
  881.   WITH ptr^ DO
  882.     IF hasSelectedEntries (ptr, firstSel)
  883.     THEN
  884.       count := countSelectedEntries (ptr);
  885.       IF (count = 0) OR (count = maxPos + 1) THEN 
  886.         IF removeSel THEN 
  887.           MTE.info (MTE.emptyList); 
  888.         END;
  889.         RETURN TRUE 
  890.       END;
  891.       (* Erstmal neue Startposition festlegen *)
  892.       IF ~removeSel 
  893.       THEN
  894.         (* n„chste selektierte suchen *)
  895.         IF ~(Selected IN list^[startPos].flags)
  896.         THEN
  897.           start := FindNextSelected (ptr, list^[startPos].msgNum);
  898.           IF start > maxPos 
  899.           THEN
  900.             start := FindPrevSelected (ptr, list^[startPos].msgNum);
  901.           END;
  902.         ELSE
  903.           start := list^[startPos].msgNum;
  904.         END;
  905.       ELSIF removeSel
  906.       THEN
  907.         IF Selected IN list^[startPos].flags
  908.         THEN
  909.           start := FindNextDeselected (ptr, list^[startPos].msgNum);
  910.           IF start > maxPos 
  911.           THEN
  912.             start := FindPrevDeselected (ptr, list^[startPos].msgNum);
  913.           END;
  914.         ELSE
  915.           start := list^[startPos].msgNum;
  916.         END;
  917.       END;
  918.       IF wholeList = list
  919.       THEN
  920.         list := NIL;
  921.         IF removeSel
  922.         THEN
  923.           ALLOCATE (list, LONG(maxPos - count + 1) * TSIZE (listEntry));
  924.         ELSE
  925.           ALLOCATE (list, LONG(count) * TSIZE (listEntry));
  926.         END;
  927.         IF list = NIL
  928.         THEN 
  929.           MTE.noMemAlert();
  930.           RETURN FALSE
  931.         END;
  932.         allocNew := TRUE;
  933.         oldList := wholeList;
  934.       ELSE
  935.         oldList := list;
  936.         allocNew := FALSE;
  937.       END;
  938.       (* Und jetzt die Liste verkleinern *)
  939.       j := 0;
  940.       FOR i := 0 TO maxPos DO 
  941.         IF (removeSel & ~(Selected IN oldList^[i].flags)) 
  942.         OR (~removeSel & (Selected IN oldList^[i].flags))
  943.         THEN
  944.           list^[j] := oldList^[i]; 
  945.           INC (j);
  946.         END;
  947.       END;
  948.       IF ~allocNew 
  949.       THEN
  950.         (* Speicherbereich verkleinern *)
  951.         IF removeSel
  952.         THEN
  953.           DEALLOCATE (list, LONG(count) * TSIZE (listEntry));
  954.         ELSE
  955.           DEALLOCATE (list, LONG (maxPos+1-count) * TSIZE (listEntry));
  956.         END;
  957.       END;
  958.       IF removeSel 
  959.       THEN
  960.         maxPos := maxPos - count;
  961.       ELSE
  962.         maxPos := count - 1;
  963.       END;
  964.       findMsgIdx (ptr, start, startPos);
  965.       (* startPos := BinOps.LowerCard (startPos, maxPos); *)
  966.       IF startPos > maxPos THEN startPos := 0 END;
  967.       IF startPos + CARDINAL(windLines) > maxPos THEN 
  968.         IF CARDINAL(windLines) > maxPos
  969.         THEN
  970.           startPos := 0
  971.         ELSE
  972.           startPos := maxPos - CARDINAL(windLines);
  973.         END;
  974.       END;
  975.       cursPos := -1;
  976.       (* Neues Document setzen *)
  977.       IF doRedraw
  978.       THEN
  979.         WdwManager.SetNewDocument (wdw, GrafBase.LongRect{LONG(leftOffset), startPos, LONG(maxWidth), maxPos}, FALSE);
  980.         WdwManager.FullRedrawWdw (wdw);
  981.       END;
  982.       RETURN TRUE
  983.     END;
  984.     RETURN FALSE
  985.   END;
  986. END shrinkList;
  987.  
  988. PROCEDURE showAll (ptr : listWdwPtr);
  989.   VAR start : CARDINAL;
  990. BEGIN
  991.   WITH ptr^ DO
  992.     IF list # wholeList
  993.     THEN
  994.       start := list^[startPos].msgNum;
  995.       (* deallocate list *)
  996.       DEALLOCATE (list, 0);
  997.       list := wholeList;
  998.       maxPos := data.LastMsgOfGroup (grHandle^.group);
  999.       findMsgIdx (ptr, start, startPos);
  1000.       startPos := BinOps.LowerCard (startPos, maxPos);
  1001.       cursPos := -1;
  1002.       WdwManager.SetNewDocument (wdw, GrafBase.LongRect{LONG(leftOffset), startPos, LONG(maxWidth), maxPos}, FALSE);
  1003.       WdwManager.FullRedrawWdw (wdw);
  1004.     END;
  1005.   END;
  1006. END showAll;
  1007.  
  1008. (*$H+*)
  1009. PROCEDURE selectTree (ptr: listWdwPtr; doRedraw: BOOLEAN);
  1010.   VAR firstSel : CARDINAL;
  1011.       i        : CARDINAL;
  1012.  
  1013.   (*$H+*)
  1014.   PROCEDURE selTree (handle: data.OneGroupHandle; 
  1015.                      msgIdx: CARDINAL;
  1016.                      mess  : dataSys.pBlockPtr);
  1017.     VAR i : CARDINAL;
  1018.   BEGIN
  1019.     (* search for mess *)
  1020.     WITH ptr^ DO
  1021.       (* First try normal list *)
  1022.       IF (msgIdx <= maxPos) & (list^[msgIdx].msgNum = msgIdx)
  1023.       THEN
  1024.         INCL (list^[msgIdx].flags, Selected);
  1025.         EXCL (list^[msgIdx].flags, inTree);
  1026.         RETURN 
  1027.       END;
  1028.       (* Not found, search from end *)
  1029.       i := maxPos;
  1030.       WHILE (list^[i].msgNum # msgIdx) & (i > 0) DO DEC (i) END;
  1031.       IF list^[i].msgNum = msgIdx 
  1032.       THEN
  1033.         INCL (list^[i].flags, Selected);
  1034.         EXCL (list^[i].flags, inTree);
  1035.       END;
  1036.     END;
  1037.   END selTree;
  1038.   
  1039. BEGIN
  1040.   WITH ptr^ DO
  1041.     IF hasSelectedEntries (ptr, firstSel)
  1042.     THEN
  1043.       (* Fr alle selektierten Nachrichten das inTree-Flag setzen *)
  1044.       FOR i := firstSel TO maxPos DO
  1045.         IF (Selected IN list^[i].flags) THEN
  1046.           INCL (list^[i].flags, inTree);
  1047.         END;
  1048.       END;
  1049.       FOR i := firstSel TO maxPos DO
  1050.         IF (inTree IN list^[i].flags) THEN
  1051.           (* Alle Nachrichten im Baum selektieren *)
  1052.           data.WalkTree (grHandle^.Zugriff, list^[i].msgNum, TRUE, selTree);
  1053.         END;
  1054.       END;
  1055.       IF doRedraw
  1056.       THEN
  1057.         (* Alles neuzeichnen *)
  1058.         WdwManager.FullRedrawWdw (wdw);
  1059.       END;
  1060.     END;
  1061.   END;
  1062. END selectTree;
  1063.  
  1064. PROCEDURE selectFromTop (ptr: listWdwPtr);
  1065.   VAR i : CARDINAL;
  1066. BEGIN
  1067.   WITH ptr^ DO
  1068.     FOR i := startPos TO maxPos DO 
  1069.       INCL (list^[i].flags, Selected);
  1070.     END;
  1071.     WdwManager.FullRedrawWdw (wdw);
  1072.   END;
  1073. END selectFromTop;
  1074.  
  1075. PROCEDURE removeTree (ptr: listWdwPtr);
  1076.   VAR firstSel : CARDINAL;
  1077. BEGIN
  1078.   WITH ptr^ DO
  1079.     IF hasSelectedEntries (ptr, firstSel)
  1080.     THEN
  1081.       (* ok, ready, set, go *)
  1082.       selectTree (ptr, FALSE);
  1083.       (* And now remove selected *)
  1084.       IF ~shrinkList (ptr, TRUE, TRUE)
  1085.       THEN
  1086.         (* Redraw wird schon in shrinkList gemacht, wenn TRUE zurckkommt *)
  1087.         WdwManager.FullRedrawWdw (wdw);
  1088.       END;
  1089.     END;
  1090.   END;
  1091. END removeTree;
  1092.  
  1093. PROCEDURE listSelectFiltered(wdw : INTEGER; doSelect: BOOLEAN; doRedraw: BOOLEAN);
  1094. (* Alle Nachrichten in dem Fenster werden selektiert *)
  1095.   VAR p : listWdwPtr;
  1096.       i : CARDINAL;
  1097.       bits : BITSET;
  1098. BEGIN
  1099.   IF handlePool.FindEntry(ADR(wdw), FindWinCond, windows, p) THEN
  1100.     WITH p^ DO
  1101.       CatGlobal.busyMouse();
  1102.       FOR i := 0 TO maxPos DO
  1103.         data.ReadState (grHandle^.Zugriff, list^[i].msgNum, bits);
  1104.         IF dataSys.bFiltered IN bits THEN
  1105.           IF doSelect
  1106.           THEN
  1107.             INCL (list^[i].flags, Selected);
  1108.           ELSE
  1109.             EXCL (list^[i].flags, Selected);
  1110.           END;
  1111.         END;
  1112.         IF (i MOD 75) = 0 THEN
  1113.           CatGlobal.busyMouse();
  1114.         END;
  1115.       END;
  1116.       mtAppl.MouseArrow();
  1117.     END;
  1118.     IF doRedraw
  1119.     THEN
  1120.       (* Und jetzt vorsichtshalber Redraw ausl”sen *)
  1121.       WdwManager.FullRedrawWdw (wdw);
  1122.     END;
  1123.   END;
  1124. END listSelectFiltered;
  1125.  
  1126. PROCEDURE openSelected (ptr : listWdwPtr; doNotTop: BOOLEAN; withCtrl : BOOLEAN);
  1127.   VAR firstSel : CARDINAL;
  1128.       isOpen   : BOOLEAN;
  1129.       nextMsg  : grin.grinNextMessProc;
  1130.       window   : INTEGER;
  1131.       group,
  1132.       mess     : CARDINAL;
  1133.       i        : CARDINAL;
  1134.       bits     : BITSET;
  1135. BEGIN
  1136.   WITH ptr^ DO
  1137.     IF hasSelectedEntries (ptr, firstSel)
  1138.     THEN
  1139.       IF countSelectedEntries (ptr) > 1
  1140.       THEN
  1141.         nextMsg := listNextMess;
  1142.         (* Jetzt vorarbeiten fr Gelesene ignorieren *)
  1143.         FOR i := firstSel TO maxPos DO 
  1144.           IF (Selected IN list^[i].flags)
  1145.           THEN
  1146.             (* Statusbits lesen *)
  1147.             data.ReadState (grHandle^.Zugriff, list^[i].msgNum, bits);
  1148.             IF dataSys.bGelesen IN bits
  1149.             THEN
  1150.               INCL (list^[i].flags, initRead);
  1151.             ELSE
  1152.               EXCL (list^[i].flags, initRead);
  1153.             END;
  1154.           ELSE
  1155.             EXCL (list^[i].flags, initRead);
  1156.           END;
  1157.         END;
  1158.       ELSE
  1159.         nextMsg := grin.grinNextMess;
  1160.       END;
  1161.       isOpen := FALSE;
  1162.       IF (grinWindow >= 0) & ~withCtrl
  1163.       THEN
  1164.         IF grin.grinWindowTop (grinWindow) & 
  1165.           (grin.ActualGroupNr (grinWindow) = grHandle^.group)
  1166.         THEN
  1167.           isOpen := grin.grinSwitchTo (grinWindow, list^[firstSel].msgNum, nextMsg, LONGCARD(ptr), doNotTop);
  1168.           IF isOpen 
  1169.           THEN
  1170.             IF usedByGrin = 0 THEN INC (usedByGrin) END;
  1171.           END;
  1172.         ELSE
  1173.           grinWindow := -1;
  1174.         END;
  1175.       END;
  1176.       IF ~isOpen
  1177.       THEN
  1178.         INC(usedByGrin);
  1179.         window := grin.grinOpenMessage (grHandle^.group, list^[firstSel].msgNum, nextMsg, LONGCARD(ptr), openMode);
  1180.         (* Nun Anfragen, welches Grinfenster nun top ist *)
  1181.         IF (window >= 0) & grin.grinWindowTop (window)
  1182.          & grin.getBasicInfo (window, group, mess, v.lcard)
  1183.          & (group = grHandle^.group) & (mess = list^[firstSel].msgNum)
  1184.         THEN
  1185.           grinWindow := window;
  1186.         END;
  1187.       END;
  1188.     END;
  1189.   END;
  1190. END openSelected;
  1191.  
  1192. PROCEDURE freeList (ptr : listWdwPtr);
  1193. BEGIN
  1194.   WITH ptr^ DO
  1195.     IF list # NIL THEN
  1196.       IF (list # wholeList)
  1197.       THEN
  1198.         DEALLOCATE (list, 0);
  1199.         list := NIL;
  1200.       END;
  1201.       DEALLOCATE (wholeList, 0);
  1202.       wholeList := NIL;
  1203.     END;
  1204.   END;
  1205. END freeList;
  1206.  
  1207. PROCEDURE testBreak (): BOOLEAN;
  1208. VAR char, scan : CHAR; kstate : BITSET;
  1209. BEGIN
  1210.   IF VDIUtil.isKey(kstate, scan, char) & (char = 33C)
  1211.   THEN
  1212.     v.int := mtAlerts.Alert (2, MTE.sortBreak);
  1213.     RETURN v.int = 1;
  1214.   END;
  1215.   RETURN FALSE
  1216. END testBreak;
  1217.  
  1218. VAR ignoreCase: BOOLEAN;
  1219.  
  1220. PROCEDURE strCmp (REF s1, s2: ARRAY OF CHAR): MagicStrings.Relation;
  1221. BEGIN
  1222.   IF ignoreCase
  1223.   THEN
  1224.     RETURN AssFuncs.StrICompare (s1, s2);
  1225.   ELSE
  1226.     RETURN MagicStrings.Compare (s1, s2);
  1227.   END
  1228. END strCmp;
  1229.  
  1230. PROCEDURE nameCompare (REF str1, str2: ARRAY OF CHAR): MagicStrings.Relation;
  1231.   VAR n1, n2 : CatTypes.String255;
  1232.       p1, p2 : INTEGER;
  1233.       x1, x2 : INTEGER;
  1234.       v1, v2 : CatTypes.String255;
  1235.       r      : MagicStrings.Relation;
  1236. BEGIN
  1237.   (* Erstmal Nachnamen suchen *)
  1238.   p1 := Strings.Pos (' ', str1, 0);
  1239.   IF p1 > 0
  1240.   THEN
  1241.     Strings.Copy (str1, 0, p1, v1, v.bool);
  1242.     Strings.Copy (str1, p1+1, INTEGER(LENGTH (str1)) - p1 - 1, n1, v.bool);
  1243.     (* Noch nach @ suchen und abschneiden! *)
  1244.     x1 := Strings.Pos ('@', n1, p1);
  1245.     IF x1 > 0
  1246.     THEN
  1247.       n1[x1] := 0c;
  1248.     END;
  1249.   END;
  1250.   p2 := Strings.Pos (' ', str2, 0);
  1251.   IF p2 > 0
  1252.   THEN
  1253.     Strings.Copy (str2, 0, p2, v2, v.bool);
  1254.     Strings.Copy (str2, p2+1, INTEGER(LENGTH (str2)) - p2 - 1, n2, v.bool);
  1255.     x2 := Strings.Pos ('@', n2, p2);
  1256.     IF x2 > 0
  1257.     THEN
  1258.       n2[x2] := 0c;
  1259.     END;
  1260.   END;
  1261.   IF (p1 > 0) & (p2 > 0)
  1262.   THEN
  1263.     (* Und jetzt k”nnen wir vergleichen *)
  1264.     r := strCmp (n1, n2);
  1265.     IF r = MagicStrings.equal
  1266.     THEN
  1267.       RETURN strCmp (v1, v2);
  1268.     END;
  1269.     RETURN r
  1270.   ELSIF (p1 > 0)
  1271.   THEN
  1272.     (* Vergleich von Nachnamen mit Namen *)
  1273.     r := strCmp (n1, str2);
  1274.     IF r = MagicStrings.equal
  1275.     THEN
  1276.       (* Vergleich von Vornamen mit Namen *)
  1277.       RETURN strCmp (v1, str2);
  1278.     END;
  1279.     RETURN r
  1280.   ELSIF (p2 > 0)
  1281.   THEN
  1282.     (* Vergleich von Nachnamen mit Namen *)
  1283.     r := strCmp (str1, n2);
  1284.     IF r = MagicStrings.equal
  1285.     THEN
  1286.       (* Vergleich von Vornamen mit Namen *)
  1287.       RETURN strCmp (str1, v2);
  1288.     END;
  1289.     RETURN r
  1290.   END;
  1291.   RETURN strCmp (str1, str2);
  1292. END nameCompare;
  1293.   
  1294.  
  1295. (*$H+*)
  1296. PROCEDURE doSort(VAR ptr : listWdwPtr; sort: sortType; withRedraw: BOOLEAN);
  1297.   VAR start, end : CARDINAL; 
  1298.       i          : CARDINAL;
  1299.       cmpCount   : LONGCARD;
  1300.  
  1301.   PROCEDURE compNum (e1, e2 : ADDRESS): BOOLEAN;
  1302.     VAR x, y : listEntryPtr;
  1303.   BEGIN
  1304.     IF cmpCount MOD 25 = 0 THEN CatGlobal.busyMouse() END;
  1305.     INC (cmpCount);
  1306.     x := listEntryPtr (e1);
  1307.     y := listEntryPtr (e2);
  1308.     RETURN x^.msgNum < y^.msgNum
  1309.   END compNum; 
  1310.   
  1311.   PROCEDURE compTree (e1, e2 : ADDRESS): BOOLEAN;
  1312.     VAR x, y : listEntryPtr;
  1313.   BEGIN
  1314.     IF cmpCount MOD 25 = 0 THEN CatGlobal.busyMouse() END;
  1315.     INC (cmpCount);
  1316.     x := listEntryPtr (e1);
  1317.     y := listEntryPtr (e2);
  1318.     IF x^.treeNum = y^.treeNum
  1319.     THEN
  1320.       RETURN x^.msgNum < y^.msgNum
  1321.     ELSE
  1322.       RETURN x^.treeNum < y^.treeNum;
  1323.     END;
  1324.   END compTree; 
  1325.   
  1326.   PROCEDURE compSize (e1, e2 : ADDRESS): BOOLEAN;
  1327.     VAR x, y : listEntryPtr;
  1328.         mess1: data.MessageType;
  1329.   BEGIN
  1330.     IF cmpCount MOD 25 = 0 THEN CatGlobal.busyMouse() END;
  1331.     INC (cmpCount);
  1332.     x := listEntryPtr (e1);
  1333.     y := listEntryPtr (e2);
  1334.     IF x^.treeNum = 0
  1335.     THEN
  1336.       data.ReadHeader (ptr^.grHandle^.Zugriff, x^.msgNum, mess1);
  1337.       x^.treeNum := LONG (mess1.textLen);
  1338.       DEALLOCATE (mess1.InfoStrings, 0);
  1339.     END;
  1340.     IF y^.treeNum = 0
  1341.     THEN
  1342.       data.ReadHeader (ptr^.grHandle^.Zugriff, y^.msgNum, mess1);
  1343.       y^.treeNum := LONG (mess1.textLen);
  1344.       DEALLOCATE (mess1.InfoStrings, 0);
  1345.     END;
  1346.     IF x^.treeNum = y^.treeNum
  1347.     THEN
  1348.       RETURN x^.msgNum < y^.msgNum
  1349.     ELSE
  1350.       (* Grože Nachrichten zuerst! *)
  1351.       RETURN x^.treeNum > y^.treeNum;
  1352.     END;
  1353.   END compSize; 
  1354.   
  1355.   PROCEDURE compDate (e1, e2 : ADDRESS): BOOLEAN;
  1356.     VAR x, y : listEntryPtr;
  1357.         mess1: data.MessageType;
  1358.   BEGIN
  1359.     IF cmpCount MOD 25 = 0 THEN CatGlobal.busyMouse() END;
  1360.     INC (cmpCount);
  1361.     x := listEntryPtr (e1);
  1362.     y := listEntryPtr (e2);
  1363.     IF x^.treeNum = 0
  1364.     THEN
  1365.       data.ReadSmallHeader (ptr^.grHandle^.Zugriff, x^.msgNum, mess1);
  1366.       x^.treeNum := mess1.tauschDate;
  1367.       (* DEALLOCATE (mess1.InfoStrings, 0); *)
  1368.     END;
  1369.     IF y^.treeNum = 0
  1370.     THEN
  1371.       data.ReadSmallHeader (ptr^.grHandle^.Zugriff, y^.msgNum, mess1);
  1372.       y^.treeNum := mess1.tauschDate;
  1373.       (* DEALLOCATE (mess1.InfoStrings, 0); *)
  1374.     END;
  1375.     IF x^.treeNum = y^.treeNum
  1376.     THEN
  1377.       RETURN x^.msgNum < y^.msgNum
  1378.     ELSE
  1379.       RETURN x^.treeNum < y^.treeNum;
  1380.     END;
  1381.   END compDate; 
  1382.   
  1383.   PROCEDURE compName (e1, e2 : ADDRESS): BOOLEAN;
  1384.     VAR x, y : listEntryPtr;
  1385.         mess1, 
  1386.         mess2: data.MessageType;
  1387.         comp : MagicStrings.Relation;
  1388.         str1, str2 : CatTypes.String255;
  1389.   BEGIN
  1390.     IF cmpCount MOD 25 = 0 THEN CatGlobal.busyMouse() END;
  1391.     INC (cmpCount);
  1392.     x := listEntryPtr (e1);
  1393.     y := listEntryPtr (e2);
  1394.     IF x^.strPtr = NIL 
  1395.     THEN
  1396.       data.ReadHeader (ptr^.grHandle^.Zugriff, x^.msgNum, mess1);
  1397.       IF mess1.EigeneNachricht & (mess1.Gruppe = dataSys.private)
  1398.       THEN
  1399.         MagicStrings.Assign (mess1.Empfaenger^, str1);
  1400.       ELSE
  1401.         MagicStrings.Assign (mess1.Absender^, str1);
  1402.       END;
  1403.       DEALLOCATE (mess1.InfoStrings, 0);
  1404.       ALLOCATE (x^.strPtr, LENGTH (str1)+2);
  1405.       IF x^.strPtr # NIL
  1406.       THEN 
  1407.         MagicStrings.Assign (str1, x^.strPtr^);
  1408.       END;
  1409.     ELSE
  1410.       MagicStrings.Assign (x^.strPtr^, str1);
  1411.     END;
  1412.     IF y^.strPtr = NIL
  1413.     THEN
  1414.       data.ReadHeader (ptr^.grHandle^.Zugriff, y^.msgNum, mess2);
  1415.       IF mess2.EigeneNachricht & (mess2.Gruppe = dataSys.private)
  1416.       THEN
  1417.         MagicStrings.Assign (mess2.Empfaenger^, str2);
  1418.       ELSE
  1419.         MagicStrings.Assign (mess2.Absender^, str2);
  1420.       END;
  1421.       DEALLOCATE (mess2.InfoStrings, 0);
  1422.       ALLOCATE (y^.strPtr, LENGTH (str2)+2);
  1423.       IF y^.strPtr # NIL
  1424.       THEN 
  1425.         MagicStrings.Assign (str2, y^.strPtr^);
  1426.       END;
  1427.     ELSE
  1428.       MagicStrings.Assign (y^.strPtr^, str2)
  1429.     END;
  1430.     comp := nameCompare (str1, str2);
  1431.     IF comp = MagicStrings.equal
  1432.     THEN 
  1433.       RETURN x^.msgNum < y^.msgNum
  1434.     ELSE
  1435.       RETURN comp = MagicStrings.less
  1436.     END;
  1437.   END compName; 
  1438.   
  1439.   PROCEDURE compWegen (e1, e2 : ADDRESS): BOOLEAN;
  1440.     VAR x, y : listEntryPtr;
  1441.         mess1, 
  1442.         mess2: data.MessageType;
  1443.         comp : MagicStrings.Relation;
  1444.         erg  : BOOLEAN;
  1445.         str1, str2 : CatTypes.String255;
  1446.         hasRe1,
  1447.         hasRe2: BOOLEAN;
  1448.         tmp  : ARRAY [0..4] OF CHAR;
  1449.   BEGIN
  1450.     IF cmpCount MOD 25 = 0 THEN CatGlobal.busyMouse() END;
  1451.     INC (cmpCount);
  1452.     x := listEntryPtr (e1);
  1453.     y := listEntryPtr (e2);
  1454.     IF x^.strPtr = NIL 
  1455.     THEN
  1456.       data.ReadHeader (ptr^.grHandle^.Zugriff, x^.msgNum, mess1);
  1457.       MagicStrings.Assign (mess1.Betreff^, str1);
  1458.       DEALLOCATE (mess1.InfoStrings, 0);
  1459.       ALLOCATE (x^.strPtr, LENGTH (str1)+2);
  1460.       IF x^.strPtr # NIL
  1461.       THEN 
  1462.         MagicStrings.Assign (str1, x^.strPtr^);
  1463.       END;
  1464.     ELSE
  1465.       MagicStrings.Assign (x^.strPtr^, str1);
  1466.     END;
  1467.     IF y^.strPtr = NIL
  1468.     THEN
  1469.       data.ReadHeader (ptr^.grHandle^.Zugriff, y^.msgNum, mess2);
  1470.       MagicStrings.Assign (mess2.Betreff^, str2);
  1471.       DEALLOCATE (mess2.InfoStrings, 0);
  1472.       ALLOCATE (y^.strPtr, LENGTH (str2)+2);
  1473.       IF y^.strPtr # NIL
  1474.       THEN 
  1475.         MagicStrings.Assign (str2, y^.strPtr^);
  1476.       END;
  1477.     ELSE
  1478.       MagicStrings.Assign (y^.strPtr^, str2)
  1479.     END;
  1480.     hasRe1 := FALSE;
  1481.     hasRe2 := FALSE;
  1482.     Strings.Copy (str1, 0, 3, tmp, v.bool);
  1483.     IF AssFuncs.StrIequal (tmp, "RE:")
  1484.     THEN
  1485.       Strings.Delete (str1, 0, 3, v.bool);
  1486.       Strings.DelLeadingBlanks (str1);
  1487.       hasRe1 := TRUE;
  1488.     END;
  1489.     Strings.Copy (str2, 0, 3, tmp, v.bool);
  1490.     IF AssFuncs.StrIequal (tmp, "RE:")
  1491.     THEN
  1492.       Strings.Delete (str2, 0, 3, v.bool);
  1493.       Strings.DelLeadingBlanks (str2);
  1494.       hasRe2 := TRUE;
  1495.     END;
  1496.     comp := strCmp (str1, str2);
  1497.     IF comp = MagicStrings.equal
  1498.     THEN
  1499.       IF hasRe1 & ~hasRe2
  1500.       THEN
  1501.         RETURN FALSE
  1502.       ELSIF ~hasRe1 & hasRe2
  1503.       THEN
  1504.         RETURN TRUE
  1505.       END;
  1506.       erg := x^.msgNum < y^.msgNum 
  1507.     ELSE
  1508.       erg := comp = MagicStrings.less
  1509.     END;
  1510.     RETURN erg;
  1511.   END compWegen;
  1512.   
  1513.   PROCEDURE prepareTreeSort ();
  1514.     VAR tree : LONGCARD;
  1515.         j    : CARDINAL;
  1516.  
  1517.   PROCEDURE markTree (handle: data.OneGroupHandle; 
  1518.                      msgIdx: CARDINAL;
  1519.                      mess  : dataSys.pBlockPtr);
  1520.     VAR i : CARDINAL;
  1521.   BEGIN
  1522.     (* search for mess *)
  1523.     WITH ptr^ DO
  1524.       (* First try normal list *)
  1525.       IF (msgIdx < maxPos) & (list^[msgIdx].msgNum = msgIdx) 
  1526.       THEN
  1527.         list^[msgIdx].treeNum := tree;
  1528.         RETURN 
  1529.       END;
  1530.       (* Not found, search from end *)
  1531.       i := end;
  1532.       WHILE (list^[i].msgNum # msgIdx) & (i > start) DO DEC (i) END;
  1533.       IF list^[i].msgNum = msgIdx 
  1534.       THEN
  1535.         list^[i].treeNum := tree;
  1536.       END;
  1537.     END;
  1538.   END markTree;
  1539.   
  1540.   BEGIN
  1541.     WITH ptr^ DO
  1542.       tree := 1;
  1543.       FOR j := start TO end DO 
  1544.         (* Alle durchgehen *)
  1545.         IF list^[j].treeNum = 0
  1546.         THEN
  1547.           CatGlobal.busyMouse();
  1548.           data.WalkTree (grHandle^.Zugriff, list^[j].msgNum, TRUE, markTree);
  1549.           INC (tree);
  1550.         END;
  1551.       END;
  1552.     END;
  1553.   END prepareTreeSort;
  1554.   
  1555. BEGIN
  1556.   WITH ptr^ DO
  1557.     start := startPos;
  1558.     end := maxPos;
  1559.     IF (start >= dataSys.notSaved) OR (end >= dataSys.notSaved) THEN RETURN END;
  1560.     IF (sort # sTree) & (sort # sSize) & (sort # sDate)
  1561.     THEN
  1562.       FOR i := start TO end DO 
  1563.         list^[i].strPtr := NIL
  1564.       END;
  1565.     ELSE
  1566.       FOR i := start TO end DO 
  1567.         list^[i].treeNum := 0
  1568.       END;
  1569.     END;
  1570.     cmpCount := 0;
  1571.     ConfVars.GetConfDefBool (cListCase, ignoreCase, FALSE);
  1572.     CASE sort OF
  1573.       sVon   : v.bool := QuickSort.sortIt (start, end, list^, compName, TSIZE (listEntry), testBreak); |
  1574.       sWegen : v.bool := QuickSort.sortIt (start, end, list^, compWegen, TSIZE (listEntry), testBreak); |
  1575.       sTree  : prepareTreeSort();
  1576.                v.bool := QuickSort.sortIt (start, end, list^, compTree, TSIZE (listEntry), testBreak); |
  1577.       sNum   : v.bool := QuickSort.sortIt (start, end, list^, compNum, TSIZE (listEntry), testBreak); |
  1578.       sSize  : v.bool := QuickSort.sortIt (start, end, list^, compSize, TSIZE (listEntry), testBreak); |
  1579.       sDate  : v.bool := QuickSort.sortIt (start, end, list^, compDate, TSIZE (listEntry), testBreak); |
  1580.     ELSE
  1581.     END;
  1582.     (* Allozierten Speicher wieder freigeben *)
  1583.     IF (sort # sTree) & (sort # sSize) & (sort # sDate)
  1584.     THEN
  1585.       FOR i := start TO end DO 
  1586.         IF list^[i].strPtr # NIL THEN DEALLOCATE (list^[i].strPtr, 0) END;
  1587.       END;
  1588.     END;
  1589.     IF withRedraw
  1590.     THEN
  1591.       WdwManager.FullRedrawWdw (wdw);
  1592.     END;
  1593.     mtAppl.MouseArrow();
  1594.   END;
  1595. END doSort;
  1596. (*$H=*)
  1597.  
  1598. PROCEDURE doMark(ptr : listWdwPtr; withDial: BOOLEAN);
  1599.   VAR mode   : INTEGER;
  1600.       what   : data.SearchSet;
  1601.       start,
  1602.       nr, idx: CARDINAL;
  1603.       break  : BOOLEAN;
  1604.       kstate : BITSET;
  1605.       char, 
  1606.       scan   : CHAR;
  1607.       
  1608. BEGIN
  1609.   WITH ptr^ DO
  1610.     IF withDial THEN
  1611.       mode := ZSearchDial.DoSearchDial (TRUE);
  1612.       IF mode < 0 THEN RETURN END;
  1613.     ELSE
  1614.       mode := ZSearchDial.FASTAHEAD
  1615.     END;
  1616.     IF SearchHelp.suchVar.searchStr[0, 0] = 0C THEN
  1617.       SearchHelp.suchVar.searchText := FALSE;
  1618.     END;
  1619.     what := data.SearchSet{};
  1620.     IF SearchHelp.suchVar.statussearch THEN INCL(what, data.inBits) END;
  1621.     IF SearchHelp.suchVar.searchText   THEN INCL(what, data.inText) END;
  1622.     IF SearchHelp.suchVar.change       THEN INCL(what, data.changeBits) END;
  1623.     IF mode = ZSearchDial.FASTBACK
  1624.     THEN
  1625.       INCL (what, data.reverse);
  1626.       (* Startmessage suchen *)
  1627.       start := 0;
  1628.       FOR idx := 0 TO startPos DO
  1629.         start := BinOps.HigherCard (start, list^[idx].msgNum);
  1630.       END;
  1631.     ELSE
  1632.       (* Startmessage suchen *)
  1633.       start := dataSys.empty;
  1634.       FOR idx := startPos TO maxPos DO 
  1635.         start := BinOps.LowerCard (start, list^[idx].msgNum);
  1636.       END;
  1637.     END;
  1638.     CatGlobal.busyMouse();
  1639.     nr := 1;
  1640.     break := FALSE;
  1641.     WHILE (nr < dataSys.notSaved) & ~break
  1642.        &  data.ComplexSearch (grHandle^.Zugriff, 
  1643.                               start, 
  1644.                               SearchHelp.suchVar.sSetBits, 
  1645.                               SearchHelp.suchVar.sClearedBits, 
  1646.                               SearchHelp.suchVar.searchStr[0],
  1647.                               SearchHelp.suchVar.searchStr[1],
  1648.                               SearchHelp.suchVar.searchStr[2],
  1649.                               SearchHelp.suchVar.searchStr[3],
  1650.                               SearchHelp.suchVar.wo[0],
  1651.                               SearchHelp.suchVar.wo[1],
  1652.                               SearchHelp.suchVar.wo[2],
  1653.                               SearchHelp.suchVar.wo[3],
  1654.                               SearchHelp.suchVar.verkn[0],
  1655.                               SearchHelp.suchVar.verkn[1],
  1656.                               SearchHelp.suchVar.verkn[2],
  1657.                               SearchHelp.suchVar.gross, 
  1658.                               SearchHelp.suchVar.setBits, 
  1659.                               SearchHelp.suchVar.clearBits, 
  1660.                               what, 
  1661.                               v.bool,
  1662.                               nr) DO
  1663.       IF nr < dataSys.notSaved
  1664.       THEN
  1665.         findMsgIdx (ptr, nr, idx);
  1666.         IF idx < dataSys.notSaved
  1667.         THEN
  1668.           IF mode = ZSearchDial.FASTBACK
  1669.           THEN
  1670.             IF idx <= startPos
  1671.             THEN
  1672.               INCL(list^[idx].flags, Selected);
  1673.             END;
  1674.           ELSE
  1675.             IF idx >= startPos
  1676.             THEN
  1677.               INCL(list^[idx].flags, Selected);
  1678.             END;
  1679.           END;
  1680.         END;
  1681.         IF mode # ZSearchDial.FASTBACK
  1682.         THEN
  1683.           start := nr+1;
  1684.         ELSE
  1685.           IF (nr > 0 ) THEN start := nr - 1; 
  1686.           ELSE
  1687.             nr := dataSys.empty;
  1688.           END;
  1689.         END;
  1690.       END;
  1691.     END;
  1692.     IF withDial
  1693.     THEN
  1694.       WdwManager.FullRedrawWdw (wdw);
  1695.     END;
  1696.     mtAppl.MouseArrow();
  1697.   END;
  1698. END doMark;
  1699.  
  1700. PROCEDURE redrawButton (wdw: INTEGER; butBox: mtUtils.tObjcTree; ob: INTEGER);
  1701.   VAR r : GrafBase.Rectangle;
  1702. BEGIN
  1703.   mtUtils.CalcArea (butBox, ob, r);
  1704.   WdwManager.RedrawWdw (wdw, r);
  1705. END redrawButton;
  1706.  
  1707. PROCEDURE careForSelected (ptr: listWdwPtr; redraw: BOOLEAN);
  1708.   CONST cSel        = ' selektiert';
  1709.         cNachricht  = ' Nachricht';
  1710.         cPlural     = 'en';
  1711.         cVon        = ' von ';
  1712.   VAR sels: CARDINAL;
  1713.       str : CatTypes.String127;
  1714. BEGIN
  1715.   WITH ptr^ DO
  1716.     sels := countSelectedEntries(ptr);
  1717.     MagicStrings.Assign ('', str);
  1718.     IF sels > 0 
  1719.     THEN
  1720.       MagicStrings.Append (StrConv.CardToStr (sels, 0), str);
  1721.       MagicStrings.Append (cVon, str);
  1722.     END;
  1723.     MagicStrings.Append (StrConv.CardToStr (maxPos+1, 0), str);
  1724.     MagicStrings.Append (cNachricht, str);
  1725.     IF maxPos > 0
  1726.     THEN
  1727.       MagicStrings.Append (cPlural, str);
  1728.     END;
  1729.     IF sels > 0
  1730.     THEN
  1731.       MagicStrings.Append (cSel, str);
  1732.     END;
  1733.     (*
  1734.     (* Nur fr Test: *)
  1735.     MagicStrings.Append (', ptr^.usedByGrin: ', str);
  1736.     MagicStrings.Append (StrConv.IntToStr (ptr^.usedByGrin, 0), str);
  1737.     *)
  1738.     mtUtils.SetObjcString (butBox, MausTauschrsc.listtext, str);
  1739.     IF redraw THEN
  1740.       redrawButton (wdw, butBox, MausTauschrsc.listtext);
  1741.     END;
  1742.   END;
  1743. END careForSelected;
  1744.  
  1745. PROCEDURE drawListWdw (wdw, vdiH : INTEGER; special : ADDRESS; frame : GrafBase.Rectangle);
  1746. VAR clip : GrafBase.Rectangle;
  1747.     ptr  : listWdwPtr;
  1748.     oldMax : INTEGER;
  1749.     eff  : INTEGER;
  1750. BEGIN
  1751.   ptr := listWdwPtr (special);
  1752.   WITH ptr^ DO
  1753.     IF isLocked THEN RETURN END;
  1754.     CASE CatGlobal.listUnreadEff OF
  1755.       0 : quoteEff := {}; |
  1756.       1 : quoteEff := {MagicVDI.Fat}; |
  1757.       2 : quoteEff := {MagicVDI.Italic}; |
  1758.       3 : quoteEff := {MagicVDI.Light}; |
  1759.     ELSE
  1760.       quoteEff := {};
  1761.     END;
  1762.     CASE CatGlobal.listOwnEff OF
  1763.       0 : ownEff := {}; |
  1764.       1 : ownEff := {MagicVDI.Fat}; |
  1765.       2 : ownEff := {MagicVDI.Italic}; |
  1766.       3 : ownEff := {MagicVDI.Light}; |
  1767.     ELSE
  1768.       ownEff := {};
  1769.     END;
  1770.     IF (mtAppl.Bitplanes = 1) 
  1771.     THEN
  1772.       CatGlobal.listUnreadCol := CatGlobal.listTextCol;
  1773.       CatGlobal.listOwnCol := CatGlobal.listTextCol;
  1774.       IF (CatGlobal.listTextCol > 0)
  1775.       THEN
  1776.         CatGlobal.listBackCol := 0;
  1777.       ELSE
  1778.         CatGlobal.listBackCol := 1;
  1779.       END;
  1780.     END;
  1781.     WdwManager.GetWdwWork (wdw, clip);
  1782.     AdjustTreePos (clip, butWork); 
  1783.     clip := frame;
  1784.     IF RectFuncs.rcIntersect (butWork, clip)
  1785.     THEN
  1786.       careForSelected (ptr, FALSE);
  1787.       VDIUtil.SetTreeColor (butBox, CatGlobal.listTextCol, CatGlobal.listBackCol);
  1788.       mtDials.DialDraw (butBox, 0, 8, clip, TRUE);
  1789.       mtAppl.MouseOff();
  1790.     END;
  1791.     clip := frame;
  1792.     IF RectFuncs.rcIntersect (listWork, clip)
  1793.     THEN
  1794.       oldMax := maxWidth;
  1795.       clip := RectFuncs.ClipRect (frame, listWork);
  1796.       clip.w := clip.x + clip.w - 1; 
  1797.       clip.h := clip.y + clip.h -1;
  1798.       
  1799.       v.int := MagicVDI.SetFillcolor (vdi, CatGlobal.listBackCol);
  1800.       MagicVDI.FillRectangle(vdi, clip);
  1801.       
  1802.       IF clip.x = listWork.x THEN
  1803.         INC (clip.x, pixOffset);
  1804.       END;
  1805.  
  1806.       clip.x := BinOps.LowerInt (clip.x, clip.w);
  1807.  
  1808.       WdwManager.SetClip (vdi, clip, FALSE);
  1809.  
  1810.       rawRedraw (ptr, clip);
  1811.       
  1812.       IF oldMax # maxWidth THEN 
  1813.         WdwManager.SetWdwDocument (wdw, GrafBase.LongRect{LONG(leftOffset), startPos, LONG(maxWidth), maxPos});
  1814.       END;
  1815.     END;
  1816.   END (* WITH ptr^ DO *);
  1817. END drawListWdw;
  1818.  
  1819. PROCEDURE checkPopups(selected: CARDINAL);
  1820.   VAR isReg : BOOLEAN;
  1821. BEGIN
  1822.   mtUtils.SetState (selPop, MausTauschrsc.lseltree, MagicAES.DISABLED, (selected = 0)); 
  1823.   mtUtils.SetState (removePop, MausTauschrsc.lremsel, MagicAES.DISABLED, (selected = 0)); 
  1824.   mtUtils.SetState (removePop, MausTauschrsc.lremnsel, MagicAES.DISABLED, (selected = 0)); 
  1825.   mtUtils.SetState (removePop, MausTauschrsc.lrembaum, MagicAES.DISABLED, (selected = 0)); 
  1826. END checkPopups;
  1827.  
  1828. PROCEDURE handleButtons (ptr : listWdwPtr; ob : INTEGER; kstate: BITSET) : BOOLEAN;
  1829.   VAR 
  1830.       i      : INTEGER;
  1831.       select : INTEGER;
  1832.       selectCount : CARDINAL;
  1833.       x, y   : INTEGER;
  1834.  
  1835. BEGIN
  1836.   WITH ptr^ DO
  1837.     IF ~mtUtils.InState (butBox, ob, MagicAES.DISABLED)
  1838.       & mtUtils.InFlag (butBox, ob, MagicAES.SELECTABLE)
  1839.     THEN
  1840.       (* Button selektieren *)
  1841.       mtUtils.InclState (butBox, ob, MagicAES.SELECTED);
  1842.       redrawButton (wdw, butBox, ob);
  1843.       (* Selektierte Nachrichten z„hlen *)
  1844.       selectCount := countSelectedEntries(ptr);
  1845.       checkPopups(selectCount);
  1846.       MagicAES.ObjcOffset (butBox, ob, x, y);
  1847.       CASE ob OF 
  1848.         MausTauschrsc.listsel : (* Selektieren *)
  1849.           (* Popup en- bzw. disablen *)
  1850.           (*
  1851.           mtUtils.SetState (selPop, MausTauschrsc.lseltree, MagicAES.DISABLED, selectCount = 0); 
  1852.           *)
  1853.           select := mtPopups.TreePopup (selPop, x, y, 0);
  1854.           CASE select OF
  1855.             MausTauschrsc.lseltree : selectTree (ptr, TRUE);
  1856.           | MausTauschrsc.lselnew  : msgList.listSelectNew (ptr^.wdw); 
  1857.           | MausTauschrsc.lselall  : msgList.listSelectAll (ptr^.wdw, TRUE); 
  1858.           | MausTauschrsc.lseltop  : selectFromTop (ptr);
  1859.           | MausTauschrsc.lselfind : doMark (ptr, TRUE); 
  1860.           | MausTauschrsc.lselinvt : invertSelection (ptr);
  1861.           | MausTauschrsc.lunselrd : deselectReadEntries (ptr); 
  1862.           | MausTauschrsc.lseldsel : deselectEntries (ptr);
  1863.  
  1864.           ELSE
  1865.           END;
  1866.       | MausTauschrsc.listshrink: (* Liste verkleinern *)
  1867.           (*
  1868.           mtUtils.SetState (removePop, MausTauschrsc.lremsel, MagicAES.DISABLED, selectCount = 0); 
  1869.           mtUtils.SetState (removePop, MausTauschrsc.lremnsel, MagicAES.DISABLED, selectCount = 0); 
  1870.           mtUtils.SetState (removePop, MausTauschrsc.lrembaum, MagicAES.DISABLED, selectCount = 0); 
  1871.           *)
  1872.           select := mtPopups.TreePopup (removePop, x, y, 0);
  1873.           CASE select OF
  1874.             MausTauschrsc.lremsel  : IF ~shrinkList (ptr, TRUE, TRUE) THEN WdwManager.FullRedrawWdw (wdw); END;
  1875.           | MausTauschrsc.lremnsel : IF ~shrinkList (ptr, FALSE, TRUE) THEN WdwManager.FullRedrawWdw (wdw); END; 
  1876.           | MausTauschrsc.lrembaum : removeTree (ptr); 
  1877.           | MausTauschrsc.lremtop  : shrinkToEnd (ptr, TRUE); 
  1878.           | MausTauschrsc.lremshow : showAll (ptr); 
  1879.           ELSE
  1880.           END;
  1881.       | MausTauschrsc.listsort: (* Sortieren *)
  1882.           select := mtPopups.TreePopup (sortPop, x, y, 0);
  1883.           IF (select >= MausTauschrsc.lsortvon) 
  1884.            & (select <= MausTauschrsc.lsortdat) 
  1885.           THEN
  1886.             doSort (ptr, sortType (select-1), TRUE);
  1887.           END;
  1888.       | MausTauschrsc.listread: (* selektierte lesen *)
  1889.           mtUtils.Bounce();
  1890.           IF selectCount = 0
  1891.           THEN
  1892.             v.int := mtAlerts.Alert (1, MTE.noneSelAlt);
  1893.             IF v.int = 1
  1894.             THEN
  1895.               msgList.listSelectAll (ptr^.wdw, FALSE);
  1896.               (* Jetzt noch schnell die gefilterten entfernen *)
  1897.               listSelectFiltered (ptr^.wdw, FALSE, TRUE);
  1898.               (* Und jetzt die noch selektierten lesen *)
  1899.               openSelected (ptr, FALSE, MagicAES.KCTRL IN kstate);
  1900.             END;
  1901.           ELSE
  1902.             openSelected (ptr, FALSE, MagicAES.KCTRL IN kstate);
  1903.           END;
  1904.       ELSE
  1905.       END;
  1906.       (* Button deselektieren *)
  1907.       mtUtils.ExclState (butBox, ob, MagicAES.SELECTED);
  1908.       redrawButton (ptr^.wdw, butBox, ob);
  1909.       careForSelected (ptr, TRUE);
  1910.       RETURN TRUE
  1911.     END;
  1912.     RETURN FALSE;
  1913.   END;
  1914. END handleButtons;
  1915.  
  1916. PROCEDURE listMoveElems (ptr: listWdwPtr; x, y : INTEGER; buts, kstate: BITSET);
  1917.   TYPE oneEntry = RECORD line: ARRAY [0..4] OF GrafBase.Point; END;
  1918.  
  1919.   VAR pointArray: POINTER TO ARRAY [0..$FFFF] OF oneEntry;
  1920.       i         : CARDINAL;
  1921.       visible   : CARDINAL;
  1922.       j         : INTEGER;
  1923.       deltaX,
  1924.       deltaY,
  1925.       oldX,
  1926.       oldY : INTEGER;
  1927.       style: CARDINAL;
  1928.       xOutput, yOutput : INTEGER;
  1929.       hdl   : INTEGER;
  1930.       size  : LONGCARD;
  1931.       siz   : CARDINAL;
  1932.       data  : ADDRESS;
  1933.       apId  : INTEGER;
  1934.  
  1935.   PROCEDURE drawLines();
  1936.     VAR i : CARDINAL;
  1937.   BEGIN
  1938.     mtAppl.MouseOff();
  1939.     FOR i := 0 TO visible - 1 DO
  1940.       MagicVDI.Polyline (ptr^.vdi, 5, pointArray^[i].line);
  1941.     END;
  1942.     mtAppl.MouseOn();
  1943.   END drawLines;
  1944.   
  1945. BEGIN
  1946.   WITH ptr^ DO
  1947.     (* Erstmal sichtbare selektierte herausfinden *)
  1948.     visible := 0;
  1949.     FOR i := startPos TO maxPos DO
  1950.       IF Selected IN list^[i].flags THEN INC (visible) END;
  1951.     END;
  1952.     (* Jetzt Speicher fr Linien allozieren *)
  1953.     IF visible = 0 THEN RETURN END;
  1954.     ALLOCATE (pointArray, visible * 5 * TSIZE (GrafBase.Point));
  1955.     IF pointArray = NIL THEN RETURN END;
  1956.     (* Jetzt die Koordinaten fr die selektierten in das Pointarray eintragen *)
  1957.     visible := 0;
  1958.     FOR i := startPos TO maxPos DO
  1959.       IF Selected IN list^[i].flags THEN 
  1960.         xOutput := listWork.x + pixOffset - leftOffset;
  1961.         yOutput := listWork.y + INTEGER(i - startPos) * (charHeight + lineDist) + (lineDist DIV 2);
  1962.         WITH pointArray^[visible] DO 
  1963.           line[0].x := xOutput;
  1964.           line[0].y := yOutput;
  1965.           line[1].x := xOutput+entryWidth-1;
  1966.           line[1].y := yOutput;
  1967.           line[2].x := xOutput+entryWidth-1;
  1968.           line[2].y := yOutput+charHeight-1;
  1969.           line[3].x := xOutput;
  1970.           line[3].y := yOutput+charHeight-1;
  1971.           line[4].x := xOutput;
  1972.           line[4].y := yOutput;
  1973.         END;
  1974.         INC (visible);
  1975.       END;
  1976.     END;
  1977.     (* Alte Koordinaten merken *)
  1978.     oldX := x;
  1979.     oldY := y;
  1980.     (* Clipping auf Screen setzen *)
  1981.     MagicAES.WindUpdate (MagicAES.BEGMCTRL);
  1982.     WdwManager.SetClip (vdi, WdwManager.deskSize, TRUE);
  1983.     (* Schreibmodus setzen *)
  1984.     v.int := MagicVDI.SetWritemode (vdi, MagicVDI.XOR);
  1985.     (* Linientyp setzen *)
  1986.     v.int := MagicVDI.SetLinetype (vdi, MagicVDI.User);
  1987.     IF ODD (leftOffset)
  1988.     THEN
  1989.       style := $AAAA;
  1990.     ELSE
  1991.       style := $5555;
  1992.     END;
  1993.     MagicVDI.SetUserlinestyle (vdi, style);
  1994.     v.int := MagicVDI.SetLinewidth (vdi, 1);
  1995.     v.int := MagicVDI.SetLinecolor (vdi, 1);
  1996.     (* Jetzt die Linie zeichnen *)
  1997.     mtAppl.MouseHand();
  1998.     drawLines();
  1999.     REPEAT
  2000.       MagicAES.GrafMkstate (x, y, buts, kstate);
  2001.       IF (x # oldX) OR (y # oldY)
  2002.       THEN 
  2003.         (* Linie wieder wegzeichnen an alten Koordinaten *)
  2004.         drawLines();
  2005.         (* Koordinaten anpassen *)
  2006.         deltaX := x - oldX;
  2007.         deltaY := y - oldY;
  2008.         FOR i := 0 TO visible - 1 DO 
  2009.           WITH pointArray^[i] DO
  2010.             FOR j := 0 TO 4 DO 
  2011.               INC (line[j].x, deltaX);
  2012.               INC (line[j].y, deltaY);
  2013.             END;
  2014.           END;
  2015.         END;
  2016.         (* Neue Outline zeichnen *)
  2017.         drawLines();
  2018.         oldX := x;
  2019.         oldY := y;
  2020.       END;
  2021.     UNTIL ~(0 IN buts);
  2022.     (* Outline wieder wegzeichnen *)
  2023.     drawLines();
  2024.     (* Writemode zurcksetzen *)
  2025.     v.int := MagicVDI.SetWritemode (vdi, MagicVDI.REPLACE);
  2026.     (* Clipping auf Workbereich setzen *)
  2027.     WdwManager.SetClip (vdi, listWork, TRUE);
  2028.     MagicAES.WindUpdate (MagicAES.ENDMCTRL);
  2029.     (* Drag und Drop ausfhren *)
  2030.     hdl := MagicAES.WindFind (x, y);
  2031.     IF hdl # wdw
  2032.     THEN
  2033.       MagicAES.WindUpdate (MagicAES.ENDUPDATE);
  2034.       IF ~WdwManager.WdwDDServe (wdw, x, y, kstate)
  2035.       THEN
  2036.         (* Das ganze per Message verschicken *)
  2037.         IF WdwManager.GetApId (hdl, apId)
  2038.         THEN
  2039.           currentExt := 0;
  2040.           listGetSelectedSize (ptr, size);
  2041.           listGetSelectedData (ptr, data);
  2042.           siz := SHORT (size);
  2043.           v.bool := Protokoll.Send2Filter (apId, siz, data)
  2044.         END;
  2045.       END;
  2046.       MagicAES.WindUpdate (MagicAES.BEGUPDATE);
  2047.     END;
  2048.     (* Mauszeiger zurcksetzen *)
  2049.     mtAppl.MouseArrow();
  2050.     (* Speicher freigeben *)
  2051.     DEALLOCATE (pointArray, 0);
  2052.   END;
  2053. END listMoveElems;
  2054.  
  2055. PROCEDURE clickInListWindow(win, vdiH : INTEGER; special : ADDRESS; x,y : INTEGER; kstate : BITSET; buts: BITSET; clicks : INTEGER): BOOLEAN;
  2056.   VAR transY : INTEGER;
  2057.       ptr    : listWdwPtr;
  2058.       entrySelected : BOOLEAN;
  2059.       line   : INTEGER;
  2060.       but    : BITSET;
  2061.       isOpen : BOOLEAN;
  2062.       ob     : INTEGER;
  2063.       clip   : GrafBase.Rectangle;
  2064.       kshift : BITSET;
  2065.       isSel  : BOOLEAN;
  2066.       
  2067.  
  2068.     PROCEDURE selectArea;
  2069.       VAR firstLine,
  2070.           lastLine : CARDINAL;
  2071.           i        : CARDINAL;
  2072.           r        : GrafBase.Rectangle;
  2073.           rect     : GrafBase.Rectangle;
  2074.           first    : BOOLEAN;
  2075.     BEGIN
  2076.       WITH ptr^ DO
  2077.         rect := GrafBase.Rectangle{x, y, 0, 0};
  2078.         mtAppl.MouseFinger ();
  2079.         MagicAES.GrafRubberbox (x, y, -32767, -32767, rect.w, rect.h);
  2080.         mtAppl.MouseArrow();
  2081.         
  2082.         WITH rect DO
  2083.           IF w < 0
  2084.           THEN
  2085.             INC(x, w);
  2086.             w := -w
  2087.           END;
  2088.           IF h < 0
  2089.           THEN
  2090.             INC (y, h);
  2091.             h := -h
  2092.           END;
  2093.         END;
  2094.         
  2095.         (* clippen *)
  2096.         rect := RectFuncs.ClipRect (rect, listWork);
  2097.         rect.h := BinOps.LowerInt (rect.h, listWork.y + listWork.h - 1 - rect.y);
  2098.  
  2099.         (* Jetzt testen, ob selektierbarer Bereich geschnitten wurde *)
  2100.         IF (((rect.x - listWork.x) < pixOffset) & ((rect.x + rect.w - listWork.x) < pixOffset)) OR
  2101.            (((rect.x - listWork.x) > maxWidth) & ((rect.x + rect.w - listWork.x) > maxWidth))
  2102.         THEN
  2103.           RETURN
  2104.         END;
  2105.         
  2106.         firstLine := (rect.y - listWork.y) DIV (charHeight + lineDist);
  2107.         lastLine  := (rect.y + rect.h - listWork.y) DIV (charHeight + lineDist);
  2108.         IF (rect.x - listWork.x > pixOffset) OR (rect.x + rect.w - listWork.x > pixOffset)
  2109.         THEN
  2110.           r := listWork;
  2111.           INC (r.x, pixOffset);
  2112.           r.h := charHeight + lineDist;
  2113.           first := TRUE;
  2114.           FOR i := startPos+firstLine TO startPos+lastLine DO
  2115.             IF (i >= 0) & (i <= maxPos)
  2116.             THEN
  2117.               toggleBit (list^[i].flags, Selected);
  2118.               IF (i >= startPos) & (i <= startPos + CARDINAL(windLines))
  2119.               THEN 
  2120.                 (* redraw *)
  2121.                 IF first THEN 
  2122.                   r.y := listWork.y + INTEGER(i - startPos) * (charHeight+lineDist);
  2123.                   first := FALSE
  2124.                 ELSE
  2125.                   r.h := listWork.y + INTEGER(i - startPos + 1) * (charHeight+lineDist) - r.y;
  2126.                 END;
  2127.               END;
  2128.             END;
  2129.           END;
  2130.           IF ~first THEN WdwManager.RedrawWdw (wdw, r) END;;
  2131.         END;
  2132.       END;
  2133.     END selectArea;
  2134.  
  2135. BEGIN
  2136.   ptr := listWdwPtr (special);
  2137.   WITH ptr^ DO
  2138.     (* Hier noch Baumposition anpassen *)
  2139.     WdwManager.GetWdwWork (wdw, clip);
  2140.     AdjustTreePos (clip, butWork); 
  2141.     IF RectFuncs.IsInRect (x, y, butWork)
  2142.     THEN
  2143.       ob := MagicAES.ObjcFind (butBox,  0, 8, x, y);
  2144.       IF (ob >= MausTauschrsc.listsel) & (ob <= MausTauschrsc.listread)
  2145.       THEN
  2146.         RETURN handleButtons (ptr, ob, kstate);
  2147.       END;
  2148.     ELSIF RectFuncs.IsInRect (x, y, listWork)
  2149.     THEN
  2150.       ShowCursor (ptr); (* Cursor ausschalten *)
  2151.       cursPos := -1;
  2152.       (* Zeile herausfinden *)
  2153.       line := (y - listWork.y) DIV (charHeight + lineDist);
  2154.       transY := (y - listWork.y - (lineDist DIV 2));
  2155.       entrySelected := (transY >= line*(charHeight + lineDist)) & 
  2156.                        (transY < ((line+1) * charHeight + line*lineDist)) &
  2157.                        ((x - listWork.x) >= pixOffset) &
  2158.                        ((x - listWork.x) <= maxWidth) & 
  2159.                        (CARDINAL(line)+startPos <= maxPos);
  2160.       MagicAES.GrafMkstate (x, y, but, kshift);
  2161.       isSel := entrySelected & (Selected IN list^[CARDINAL(line)+startPos].flags);
  2162.       IF ~(isSel & (0 IN but)) & ~CatGlobal.WithShift (kstate)
  2163.       THEN
  2164.         deselectEntries (ptr);
  2165.       END;
  2166.       IF entrySelected
  2167.       THEN
  2168.         IF ~(isSel & (0 IN but))
  2169.         THEN
  2170.           toggleEntry (ptr, CARDINAL(line)+startPos);
  2171.         END;
  2172.         IF (clicks > 1) OR (~(0 IN buts) & (1 IN buts))
  2173.         THEN
  2174.           openSelected (ptr, ~(0 IN buts) & (1 IN buts), MagicAES.KCTRL IN kstate);
  2175.         ELSE
  2176.           IF (0 IN but)
  2177.           THEN
  2178.             (* Drag & Drop! *)
  2179.             listMoveElems (ptr, x, y, buts, kstate);
  2180.           END;
  2181.         END;
  2182.         (* Warten auf loslassen *)
  2183.         REPEAT
  2184.           MagicAES.GrafMkstate (x, y, but, kstate);
  2185.         UNTIL but = {};
  2186.       ELSE
  2187.         MagicAES.GrafMkstate (x, y, but, kstate);
  2188.         IF 0 IN but
  2189.         THEN
  2190.           (* Graf-Rubberbox aufrufen *)
  2191.           selectArea();
  2192.         END;
  2193.       END;
  2194.       careForSelected (ptr, TRUE);
  2195.       RETURN TRUE;
  2196.     END;
  2197.   END;
  2198.   RETURN FALSE;
  2199. END clickInListWindow;
  2200.  
  2201. PROCEDURE handleListTimer (wdw, vdiH : INTEGER; special : ADDRESS): BOOLEAN;
  2202.   VAR ptr   : listWdwPtr;
  2203.       i     : CARDINAL;
  2204.       max   : CARDINAL;
  2205. BEGIN
  2206.   ptr := listWdwPtr (special);
  2207.   WITH ptr^ DO
  2208.     IF startPos < MAX(CARDINAL) - CARDINAL (windLines)
  2209.     THEN
  2210.       max := BinOps.LowerCard (startPos+CARDINAL(windLines), maxPos);
  2211.     ELSE
  2212.       max := maxPos;
  2213.     END;
  2214.     max := BinOps.LowerCard (max, maxPos);
  2215.     FOR i := startPos TO max DO
  2216.       IF doRedraw IN list^[i].flags
  2217.       THEN
  2218.         redrawEntry (ptr, i);
  2219.       END;
  2220.     END;
  2221.     RETURN TRUE;
  2222.   END;
  2223. END handleListTimer;
  2224.  
  2225. PROCEDURE handleListKey (wdw, vdiH : INTEGER; special : ADDRESS; taste: INTEGER; char, scan : CHAR; kstate : BITSET) : BOOLEAN;
  2226.   VAR ptr   : listWdwPtr;
  2227.       gemCh : CARDINAL;
  2228.       key   : MOSGlobals.Key;
  2229.       ctrl  : BOOLEAN;
  2230.       shift : BOOLEAN;
  2231.       done  : BOOLEAN;
  2232.       doc   : GrafBase.LongRect;
  2233.       firstSel  : CARDINAL;
  2234.       selChanged: BOOLEAN;
  2235.       again : BOOLEAN;
  2236.       specCode: Keyboard.SpecialCode;
  2237.       handle : BOOLEAN;
  2238.       mode   : grinTools.ActionType;
  2239. BEGIN
  2240.   ptr := listWdwPtr (special);
  2241.   WITH ptr^ DO
  2242.     selChanged := FALSE;
  2243.     gemCh := ORD(scan) * 256 + ORD(char);
  2244.     Keyboard.GemCharToKey (gemCh,  SHORT (INTEGER(kstate)), key);
  2245.     ctrl := MagicAES.KCTRL IN kstate;
  2246.     shift := CatGlobal.WithShift (kstate);
  2247.     done := TRUE;
  2248.     IF (cursPos < LONGINT(LONG(startPos))) OR (cursPos > LONGINT(LONG(startPos + CARDINAL(windLines))) - 1) 
  2249.     THEN 
  2250.       cursPos := -1 
  2251.     END;
  2252.     IF Keyboard.IsSpecial (key)
  2253.     THEN
  2254.       specCode := Keyboard.SpecialKey (key);
  2255.       REPEAT
  2256.         again := FALSE;
  2257.         CASE specCode OF
  2258.           left          : WdwManager.ScrollLeft (wdw, 1);  |
  2259.           soln          : WdwManager.PageLeft (wdw);    |
  2260.           right         : WdwManager.ScrollRight (wdw, 1); | 
  2261.           eoln          : WdwManager.PageRight (wdw);   |
  2262.           pgUp          : WdwManager.PageUp (wdw); |
  2263.           pgDown        : WdwManager.PageDown (wdw); |
  2264.           up            : IF cursPos = -1 
  2265.                           THEN 
  2266.                             cursPos := LONGINT (LONG(startPos+CARDINAL(windLines)-1));
  2267.                           ELSE
  2268.                             ShowCursor (ptr); (* alten wegmachen *) 
  2269.                             IF shift THEN
  2270.                               DEC (cursPos, windLines - 1);
  2271.                             ELSE
  2272.                               DEC (cursPos);
  2273.                             END;
  2274.                           END;
  2275.                           cursPos := BinOps.LowerLInt (maxPos, cursPos);
  2276.                           cursPos := BinOps.HigherLInt (0, cursPos);
  2277.                           IF cursPos >= LONGINT (LONG(startPos))
  2278.                           THEN
  2279.                             ShowCursor (ptr);
  2280.                           ELSE
  2281.                             IF shift 
  2282.                             THEN
  2283.                               WdwManager.PageUp (wdw);
  2284.                             ELSE
  2285.                               WdwManager.ScrollUp (wdw, 1);
  2286.                             END;
  2287.                           END;
  2288.                           (*
  2289.                           WdwManager.ScrollUp (wdw, 1); *)   |
  2290.           down          : 
  2291.                           IF cursPos = -1 
  2292.                           THEN 
  2293.                             cursPos := LONGINT (LONG(startPos));
  2294.                           ELSE
  2295.                             ShowCursor (ptr); (* alten wegmachen *) 
  2296.                             IF shift THEN
  2297.                               INC (cursPos, windLines - 1);
  2298.                             ELSE
  2299.                               INC (cursPos);
  2300.                             END;
  2301.                           END;
  2302.                           cursPos := BinOps.LowerLInt (cursPos, maxPos);
  2303.                           cursPos := BinOps.HigherLInt (0, cursPos);
  2304.                           IF cursPos <= LONGINT (LONG(startPos + CARDINAL(windLines) - 1))
  2305.                           THEN
  2306.                             ShowCursor (ptr);
  2307.                           ELSE
  2308.                             IF shift THEN
  2309.                               WdwManager.PageDown (wdw);
  2310.                             ELSE
  2311.                               WdwManager.ScrollDown (wdw, 1);
  2312.                             END;
  2313.                           END;
  2314.                           (*
  2315.                           WdwManager.ScrollDown (wdw, 1); *) |
  2316.           altL,
  2317.           return,
  2318.           enter         : v.bool := handleButtons (ptr, MausTauschrsc.listread, kstate); |
  2319.           (* Buttons in Topleiste *)        
  2320.           alt1          : v.bool := handleButtons (ptr, MausTauschrsc.listsel, kstate); |
  2321.           alt2          : v.bool := handleButtons (ptr, MausTauschrsc.listshrink, kstate); |
  2322.           alt3          : v.bool := handleButtons (ptr, MausTauschrsc.listsort, kstate); |
  2323.           (*      
  2324.           return,
  2325.           enter         : openSelected (ptr, FALSE, ctrl) ; |
  2326.           *)
  2327.           insert        : IF cursPos >= 0 THEN 
  2328.                             selChanged := TRUE; 
  2329.                             toggleEntry (ptr, SHORT(LONGCARD(cursPos)));
  2330.                             (* Jetzt um einen nach unten bewegen *)
  2331.                             again := TRUE;
  2332.                             specCode := Keyboard.down;
  2333.                           END; |
  2334.   
  2335.           home,
  2336.           clr           : IF Keyboard.SpecialKey (key) = home
  2337.                           THEN
  2338.                             startPos := 0;
  2339.                           ELSE
  2340.                             IF CARDINAL(windLines) > maxPos THEN startPos := 0
  2341.                             ELSE startPos := maxPos - CARDINAL(windLines) + 1; END;
  2342.                           END; 
  2343.                           WdwManager.SetWdwDocument (wdw, GrafBase.LongRect{LONG(leftOffset), startPos, LONG(maxWidth), maxPos});
  2344.                           |
  2345.         ELSE
  2346.           done := FALSE
  2347.         END;
  2348.       UNTIL ~again;
  2349.     ELSE
  2350.       IF char = ' '
  2351.       THEN
  2352.         WdwManager.GetWdwDocument (wdw, doc);
  2353.         IF doc.y > doc.h - LONG(windLines)
  2354.         THEN
  2355.           (* n„chste Seite nicht m”glich *)
  2356.           openSelected (ptr, FALSE, MagicAES.KCTRL IN kstate);
  2357.         ELSE
  2358.           WdwManager.PageDown (wdw);
  2359.         END;
  2360.       ELSE
  2361.         IF extendedCommentMode
  2362.         THEN
  2363.           handle := TRUE;
  2364.           CASE CAP(char) OF
  2365.             'B' : mode := grinTools.answer; |
  2366.             'G' : mode := grinTools.otherGroup; |
  2367.             'K' : mode := grinTools.comment; |
  2368.           ELSE
  2369.             handle := FALSE;
  2370.           END;
  2371.           IF handle & (countSelectedEntries (ptr) = 1)
  2372.           THEN
  2373.             (* Nachricht anzeigen und dann grintools mit Action aufrufen *)
  2374.             openSelected (ptr, FALSE, FALSE);
  2375.             grinTools.Handle (grinWindow, mode);
  2376.           ELSE
  2377.             done := FALSE;
  2378.           END;
  2379.         ELSE
  2380.           done := FALSE;
  2381.         END;
  2382.       END;
  2383.     END;
  2384.     IF selChanged THEN careForSelected(ptr, TRUE); END;
  2385.     RETURN done;
  2386.   END;
  2387. END handleListKey;
  2388.  
  2389. PROCEDURE getListScroll (wdw, vdiH : INTEGER; special : ADDRESS; VAR work : GrafBase.Rectangle);
  2390.   VAR ptr       : listWdwPtr;
  2391.       varName   : ARRAY [0..255] OF CHAR;
  2392.       full      : GrafBase.Rectangle;
  2393. BEGIN 
  2394.   ptr := listWdwPtr (special);
  2395.   AdjustTreePos (work, ptr^.butWork);
  2396.   DEC (work.h, butBox^[0].obHeight+1);
  2397.   INC (work.y, butBox^[0].obHeight+1);
  2398.   WITH work DO
  2399.     ptr^.windLines := BinOps.HigherInt (0, (BinOps.LowerInt(y+h-1, INTEGER(mtAppl.MaxHeight-1)) - y+1) DIV (ptr^.charHeight+lineDist)); 
  2400.     WdwManager.SetScrollParms (wdw, w-ptr^.charWidth, ptr^.windLines-1, ptr^.charWidth, 1);
  2401.     ptr^.listWork := work;
  2402.   END;
  2403.   WITH ptr^ DO
  2404.     IF wdw >= 0
  2405.     THEN
  2406.       Strings.Concat (cListWdw, StrConv.IntToStr (number, 0), varName, v.bool);
  2407.       WdwManager.GetWdwSize (wdw, full);                (* Gr”že des Fensters abfragen *)
  2408.       v.bool := ConfVars.SetConfigRect (varName, full);
  2409.     END;
  2410.   END;
  2411. END getListScroll;
  2412.  
  2413. PROCEDURE closeListWindow (wdw, vdiH : INTEGER; special : ADDRESS; force : BOOLEAN) : BOOLEAN;
  2414.   VAR ptr : listWdwPtr;
  2415.       varName : CatTypes.String255;
  2416.       full    : GrafBase.Rectangle;
  2417. BEGIN
  2418.   ptr := listWdwPtr (special);
  2419.   WITH ptr^ DO
  2420.     Strings.Concat (cListWdw, StrConv.IntToStr (number, 0), varName, v.bool);
  2421.     WdwManager.GetWdwSize  (wdw, full); (* Gr”že des Fensters abfragen *)
  2422.     v.bool := ConfVars.SetConfigRect (varName, full);
  2423.     Strings.Concat (cListFont, StrConv.IntToStr (number, 0), varName, v.bool);
  2424.     v.bool := ConfVars.SetConfigInt (varName, font);
  2425.     Strings.Concat (cListSize, StrConv.IntToStr (number, 0), varName, v.bool);
  2426.     v.bool := ConfVars.SetConfigInt (varName, fontSize);
  2427.     v.bool := ConfVars.SetConfigInt (cListLeftOffset, pixOffset);
  2428.     v.bool := ConfVars.SetConfigInt (cListLineDist, lineDist);
  2429.     ClearNum (number);
  2430.     FontSelect.UnloadFonts (vdi);
  2431.   END;
  2432.   IF (ptr^.usedByGrin = 0) OR force
  2433.   THEN
  2434.     freeList (ptr);
  2435.     handlePool.FreeOneDataHandle(ptr^.grHandle);
  2436.     handlePool.FreeOnePtr(ptr, windows);
  2437.   ELSE
  2438.     ptr^.wdw := -1;
  2439.     ptr^.vdi := -1;
  2440.   END;
  2441.   RETURN TRUE
  2442. END closeListWindow;
  2443.  
  2444. PROCEDURE topListWdw (wdw, vdiH : INTEGER; special : ADDRESS) : BOOLEAN;
  2445. BEGIN
  2446.   RETURN TRUE;
  2447. END topListWdw;
  2448.  
  2449. PROCEDURE untopListWdw (wdw, vdiH : INTEGER; special : ADDRESS);
  2450. END untopListWdw;
  2451.  
  2452. PROCEDURE updateListWdw (wdw, vdiH : INTEGER; special : ADDRESS; update : BOOLEAN);
  2453. BEGIN
  2454.   IF update
  2455.   THEN
  2456.     MagicAES.WindUpdate (MagicAES.BEGUPDATE);
  2457.     mtAppl.MouseOff();
  2458.   ELSE
  2459.     mtAppl.MouseOn();
  2460.     MagicAES.WindUpdate (MagicAES.ENDUPDATE);
  2461.   END;
  2462. END updateListWdw;
  2463.  
  2464. PROCEDURE hideListWdw (wdw, vdiH : INTEGER; special : ADDRESS; hide : BOOLEAN);
  2465.   VAR ptr : listWdwPtr;
  2466. BEGIN
  2467.   ptr := listWdwPtr (special);
  2468.   ptr^.isHidden := hide;
  2469. END hideListWdw;
  2470.  
  2471. PROCEDURE setListWork (wdw, vdiH : INTEGER; special : ADDRESS; doc : GrafBase.LongRect; slided : BOOLEAN);
  2472.   VAR ptr : listWdwPtr;
  2473. BEGIN
  2474.   ptr := listWdwPtr (special);
  2475.   WITH ptr^ DO
  2476.     leftOffset := SHORT(doc.x);
  2477.     startPos   := VAL (CARDINAL, doc.y);
  2478.     IF (cursPos < doc.y) OR (cursPos > doc.y + LONGINT (LONG(windLines)) - 1) 
  2479.     THEN 
  2480.       cursPos := -1 
  2481.     END;
  2482.   END;
  2483. END setListWork;
  2484.  
  2485. PROCEDURE snapListWdw (wdw, vdiH : INTEGER; special : ADDRESS; VAR work : GrafBase.Rectangle);
  2486.   CONST minWindWidth = 80;
  2487.         minWindHeight = 80;
  2488.   VAR ptr       : listWdwPtr;
  2489.       minWdwH   : INTEGER;
  2490. BEGIN
  2491.   ptr := listWdwPtr (special);
  2492.   WITH ptr^ DO
  2493.     IF font >= 0
  2494.     THEN
  2495.       AdjustTreePos (work, butWork);
  2496.       WITH work DO
  2497.         DEC (h, butWork.h);
  2498.         minWdwH := minWindHeight - butWork.h;
  2499.         INC(h);         (* Um Rundungsfehler zu vermeiden *)
  2500.         h := (h DIV (charHeight+lineDist)) * (charHeight+lineDist);
  2501.         WHILE w < minWindWidth DO INC(w, charWidth) END;
  2502.         WHILE h < minWdwH DO INC(h, charHeight+lineDist) END;
  2503.         windLines := BinOps.HigherInt (0, (BinOps.LowerInt(y+h-1, INTEGER(mtAppl.MaxHeight-1)) - y+1) DIV (charHeight+lineDist)); 
  2504.         listWork := work;
  2505.         INC (work.h, butWork.h);
  2506.         WdwManager.SetScrollParms (wdw, w-charWidth, windLines-1, charWidth, 1);
  2507.       END;
  2508.     END;
  2509.   END;
  2510. END snapListWdw;
  2511.  
  2512. CONST   cFrom = 'From: ';
  2513.         cTopic = 'Subject: ';
  2514.         cGroup = 'Group: ';
  2515.         cTAB  = 011C;
  2516.  
  2517. PROCEDURE listGetSelectedSize (ptr: listWdwPtr; VAR size: LONGCARD);
  2518. VAR   i   : CARDINAL;
  2519.       j   : INTEGER;
  2520.       sels: CARDINAL;
  2521. BEGIN
  2522.   WITH ptr^ DO
  2523.     (* Eine einfache Schleife reicht, in der ich in jeder Zeile die Bytes z„hle *)
  2524.     size := 0;
  2525.     sels := countSelectedEntries (ptr);
  2526.     IF sels > 0
  2527.     THEN
  2528.       IF currentExt = 0 (* Filter-Daten *)
  2529.       THEN
  2530.         (* Wir bergeben folgendes: 
  2531.          * From: Absender, 256 Zeichen
  2532.          * TAB
  2533.          * Topic: Betreff, 256 Zeichen
  2534.          * TAB
  2535.          *)
  2536.         size := LENGTH (cFrom) + LENGTH (cTopic) + LENGTH (cGroup) + 771 (* 256*3 + 3 *);
  2537.         size := size * LONG(sels);
  2538.       ELSE
  2539.         (* Platzbedarf einer Zeile ermitteln *)
  2540.         FOR j := 0 TO partArray.lines-1 DO
  2541.           INC (size, partArray.parts[j].w+1);
  2542.           IF currentExt = 2 (* CSV *)
  2543.           THEN INC (size, 2) (* Fr Anfhrungszeichen *) 
  2544.           END;
  2545.         END;
  2546.         INC (size);    (* Fr CR/LF *)
  2547.         (* Jetzt multiplizieren wir das nur noch mit der Anzahl der Zeilen,
  2548.          * und schon haben wir den ben”tigten Platz 
  2549.          *)
  2550.         size := size * LONG(sels);
  2551.       END;
  2552.     END;
  2553.   END;
  2554. END listGetSelectedSize;
  2555.  
  2556. PROCEDURE listGetSelectedData (ptr: listWdwPtr; VAR adr: ADDRESS);
  2557. CONST
  2558.         LF =            12C;
  2559.         CR =            15C;
  2560.  
  2561.   VAR text: CatTypes.LargeTextPtr;
  2562.       idx : LONGCARD;
  2563.       i   : CARDINAL;
  2564.       k   : LONGCARD;
  2565.       j   : INTEGER;
  2566.       mess: data.MessageType;
  2567.       line: ARRAY [0..1023] OF CHAR;
  2568.       gName: CatTypes.String255;
  2569. BEGIN
  2570.   WITH ptr^ DO
  2571.     IF dataSize > 0 THEN INC (dataSize) END;
  2572.     ALLOCATE (adr, dataSize);
  2573.     IF adr = NIL THEN RETURN END;
  2574.     text := adr;
  2575.     idx := 0;
  2576.     (* Eine einfache Schleife reicht, in der ich in jeder Zeile die Bytes z„hle *)
  2577.     FOR i := 0 TO maxPos DO
  2578.       IF Selected IN list^[i].flags THEN 
  2579.         (* Header der Message lesen *)
  2580.         data.ReadHeader (grHandle^.Zugriff, list^[i].msgNum, mess);
  2581.         IF data.error # data.noError
  2582.         THEN
  2583.           WITH mess DO
  2584.             MailID := NIL;
  2585.             Betreff := NIL;
  2586.             Absender := NIL;
  2587.             Empfaenger := NIL;
  2588.             mid := NIL;
  2589.             rid := NIL;
  2590.             box := NIL;
  2591.             name := NIL;
  2592.             InfoStrings := NIL;
  2593.           END;
  2594.         END;
  2595.         IF currentExt = 0 (* Filterdaten *)
  2596.         THEN
  2597.           Block.Copy (CADR(cFrom), LENGTH (cFrom), ADR(text^[idx]));
  2598.           INC (idx, LENGTH (cFrom));
  2599.           (* Feld kopieren *)
  2600.           FOR k := 0 TO 255 DO
  2601.             text^[idx+k] := ' ';
  2602.           END;
  2603.           IF mess.Absender # NIL
  2604.           THEN 
  2605.             Block.Copy (mess.Absender, LENGTH (mess.Absender^), ADR(text^[idx]));
  2606.           END;
  2607.           INC (idx, 256);
  2608.           Block.Copy (CADR(cTAB), 1, ADR(text^[idx]));
  2609.           INC (idx);
  2610.           Block.Copy (CADR(cTopic), LENGTH (cTopic), ADR(text^[idx]));
  2611.           INC (idx, LENGTH (cTopic));
  2612.           (* zweites Feld kopieren *)
  2613.           FOR k := 0 TO 255 DO
  2614.             text^[idx+k] := ' ';
  2615.           END;
  2616.           IF mess.Betreff # NIL
  2617.           THEN 
  2618.             Block.Copy (mess.Betreff, LENGTH (mess.Betreff^), ADR(text^[idx]));
  2619.           END;
  2620.           INC (idx, 256);
  2621.           Block.Copy (CADR(cTAB), 1, ADR(text^[idx]));
  2622.           INC (idx);
  2623.           (* Gruppe anh„ngen *)
  2624.           Block.Copy (CADR(cGroup), LENGTH (cGroup), ADR(text^[idx]));
  2625.           INC (idx, LENGTH (cGroup));
  2626.           (* zweites Feld kopieren *)
  2627.           FOR k := 0 TO 255 DO
  2628.             text^[idx+k] := ' ';
  2629.           END;
  2630.           GroupSelect.GroupName (mess.Gruppe, gName);
  2631.           Block.Copy (ADR(gName), LENGTH (gName), ADR(text^[idx]));
  2632.           INC (idx, 256);
  2633.           Block.Copy (CADR(cTAB), 1, ADR(text^[idx]));
  2634.           INC (idx);
  2635.         ELSE
  2636.           (* Zeile aufbauen und Bytes z„hlen *)
  2637.           FOR j := 0 TO partArray.lines-1 DO
  2638.             IF currentExt = 2 (* CSV *)
  2639.             THEN 
  2640.               (* Ein Anfhrungszeichen schreiben *)
  2641.               text^[idx] := '"';
  2642.               INC (idx);
  2643.             END;
  2644.             GetLinePart (ptr, list^[i].msgNum, mess, line, partArray.parts[j]);
  2645.             Strings.Append (Strings.Space (partArray.parts[j].w - INTEGER(LENGTH (line))), line, v.bool);
  2646.             Block.Copy (ADR(line), partArray.parts[j].w, ADR(text^[idx]));
  2647.             INC (idx, partArray.parts[j].w);
  2648.             IF currentExt = 2 (* CSV *)
  2649.             THEN 
  2650.               (* Ein Anfhrungszeichen schreiben *)
  2651.               text^[idx] := '"';
  2652.               INC (idx);
  2653.             END;
  2654.             (* Eintr„ge mit Komma trennen *)
  2655.             IF j < partArray.lines-1 THEN
  2656.               IF currentExt = 2 THEN
  2657.                 text^[idx] := ',';
  2658.               ELSE
  2659.                 text^[idx] := ' ';
  2660.               END;
  2661.               INC (idx);
  2662.             END;
  2663.           END; (* FOR j *)
  2664.           text^[idx] := CR;
  2665.           text^[idx+1] := LF;
  2666.           INC (idx, 2);
  2667.         END;
  2668.         (* Speicher freigeben *)
  2669.         IF mess.InfoStrings # NIL THEN 
  2670.           DEALLOCATE (mess.InfoStrings, 0);
  2671.         END;
  2672.       END;
  2673.     END;
  2674.     IF (idx >= dataSize) THEN 
  2675.       HALT 
  2676.     ELSE
  2677.       text^[idx] := 0C;
  2678.     END;
  2679.   END;
  2680. END listGetSelectedData;
  2681.  
  2682. TYPE listExtsType   = ARRAY [0..7] OF ARRAY [0..3] OF CHAR;
  2683.  
  2684. CONST listExts = listExtsType{'.FLT','.TXT','.CSV',0C+0C+0C+0C BY 5};
  2685.       maxSendExts   = 3;
  2686.  
  2687. PROCEDURE listGetHeader (wdw: INTEGER; special: ADDRESS; mode: INTEGER;
  2688.                          VAR ext, name : ARRAY OF CHAR; VAR size: LONGCARD): BOOLEAN;
  2689.  
  2690. CONST   cListName  = 'CAT Messageliste'+0C;
  2691.         cFiltName  = 'CAT Filterinformation'+0C;
  2692.  
  2693.   VAR ptr   : listWdwPtr;
  2694. BEGIN
  2695.   ptr := listWdwPtr (special);
  2696.   WITH ptr^ DO
  2697.     IF mode = WdwManager.HDRFIRST
  2698.     THEN 
  2699.       currentExt := 0;
  2700.     ELSE
  2701.       INC (currentExt);
  2702.     END;
  2703.     IF currentExt >= maxSendExts THEN RETURN FALSE END;
  2704.     Strings.Assign (listExts[currentExt], ext, v.bool);
  2705.     IF currentExt = 0
  2706.     THEN
  2707.       Strings.Assign (cFiltName, name, v.bool);
  2708.     ELSE
  2709.       Strings.Assign (cListName, name, v.bool);
  2710.     END;
  2711.     listGetSelectedSize (ptr, size);
  2712.     dataSize := size;
  2713.     RETURN size > 0;
  2714.   END;
  2715. END listGetHeader;
  2716.  
  2717. PROCEDURE listReadData (wdw: INTEGER; special: ADDRESS; VAR data: ADDRESS);
  2718.   VAR ptr   : listWdwPtr;
  2719. BEGIN
  2720.   ptr := listWdwPtr (special);
  2721.   WITH ptr^ DO
  2722.     listGetSelectedData (ptr, data);
  2723.   END;
  2724. END listReadData;
  2725.  
  2726. PROCEDURE MakeTitle (gruppe: CARDINAL; VAR title: ARRAY OF CHAR);
  2727. BEGIN
  2728.   GroupSelect.GroupName (gruppe, title);
  2729.   ConfVars.GetConfDefBool (cSetAppName, v.bool, TRUE);
  2730.   IF CatGlobal.multiTask & v.bool
  2731.   THEN
  2732.     MagicStrings.Insert ('[CAT] ', title, 0);
  2733.   END;
  2734.   MagicStrings.Insert (' ', title, 0);
  2735.   MagicStrings.Append (' ', title);
  2736. END MakeTitle;
  2737.  
  2738. END MsgListBase.
  2739.